PYTHON模拟BINLOG文件损坏 以及 解决办法
导读
mysql的binlog 被用来做主从, 实时备份等, 可谓非常重要(redo log你在干嘛....)
如果你经常使用Binlog的话, 你可能会遇到如下报错
ERROR: Error in Log_event::read_log_event(): 'Found invalid event in binary log', data_len: 61, event_type: 44
ERROR: Could not read entry at offset 1195: Error in log format or read error.
咋办呢? 如果是从库的话, 重建从库就行(就是比较麻烦). 如果是实时备份或者需要分析Binlog的时候 咋办呢?
PYTHON模拟binlog文件损坏
我们只需要修改event_header的某些值, 那么这个binlog文件就会被认为已经损坏了.
关于binlog的结构, 可以看我之前写的 BINLOG文件解析 这里就不再介绍了
老规矩, 本文提供的脚本在文末
拷贝一个Binlog过来
本文是模拟环境, 所以不要去修改真实环境, 就拷贝一个文件意思意思
cp -ra /data/mysql_3308/mysqllog/binlog/m3308.001014 .
执行脚本,破坏Binlog
本次只修改event_type即可, 因为多数报错都是报这个错
import binlog_tool
aa = binlog_tool.listevent('m3308.001014') #参数为binlog文件路径
aa[14] #查看第14个event信息
binlog_tool.mevent_type('m3308.001014',1676,66) #binlog文件名 起始pos号 修改的新的event_type值
aa = binlog_tool.listevent('m3308.001014')
aa[14] #再次确认是否修改成功
33代表GTID_LOG_EVENT使用mysqlbinlog解析发现报错
说明我们确实破坏了binlog, 那么现在咋办呢?
event_type确实是我们刚才修改的值解决办法
既然这个event坏了, 那我们就不要这个event了. (壮士断腕.jpg)
1. binlog_tool.listevent
如果你使用了我提供的 binlog_tool.listevent
去解析binlog的话, 你就能看到下一个event的地址(end_pos), 直接指定从下一个地址开始即可
mysqlbinlog --start-position=1737 m3308.001014 >
/dev/null #本次实验是1737
然后把两次解析的结果拼起来就行. (之前报错的时候, 前面部分是解析正常的)
一个个POS号往后加
如果你没有使用我给的工具的话, 你就的自己一个个pos号往后试了 -_-
虽然麻烦点, 但也能用....总结
binlog损坏的场景并不常见(sync_binlog=1的环境,binlog写失败事务就回滚了), 但是遇到了还是得有解决的办法才行.
1. 跳过有问题的event 可能会丢数据. 不过本次有问题的event是gtid, 所以不会丢数据
2. sync_binlog设置为1很重要. 起码你最多就丢一个事务.
3. 会一门编程语言,对dba运维好处很大. 能解决很多问题.
附源码
其实我还给了个read_event的函数, 方便你去分析有问题的那个event. 只不过本文未演示而已
import struct
import os
def listevent(filename='m3308.001014',):
el = []
with open(filename,'rb') as f:
magic = f.read(4)
if magic != b'\xfebin':
return []
while True:
header = f.read(19)
if len(header) == 19:
timestamp, event_type, server_id, event_size, log_pos, flags = struct.unpack("LBLLLh",header[0:19])
el.append({
'timestamp':timestamp,'start_pos':f.tell()-19,'end_pos':log_pos,'size':event_size,'event_type':event_type}
)
event_body = f.read(event_size-19)
else:
print('endsize:',f.tell(),'event_count',len(el))
break
return el
def mevent_type(filename='m3308.001014',start_pos=4,new_value=250):
f = os.open(filename, os.O_RDWR|os.O_CREAT, 0o644)
os.lseek(f, start_pos+4, 0)
os.write(f, struct.pack('B',new_value))
os.close(f)
return True
def read_event(filename='m3308.001014',start_pos=4,max_size=100000):
with open(filename,'rb') as f:
f.seek(start_pos,0)
header = f.read(19)
timestamp, event_type, server_id, event_size, log_pos, flags = struct.unpack("LBLLLh",header[0:19])
if event_size max_size:
event_body = f.read(event_size-19)
return {
'timestamp':timestamp,'event_type':event_type,'server_id':server_id,'event_size':event_size,'log_pos':log_pos,'flags':flags,'event_body':event_body}
else:
return None
声明:本文内容由网友自发贡献,本站不承担相应法律责任。对本内容有异议或投诉,请联系2913721942#qq.com核实处理,我们将尽快回复您,谢谢合作!
若转载请注明出处: PYTHON模拟BINLOG文件损坏 以及 解决办法
本文地址: https://pptw.com/jishu/861.html