场景:某DBA在数据操作过程中,误将db.t1执行了一次delete from db.t1;,此数据库配置的格式为row,现在需要利用binlog将该误操作进行恢复。
1、获取删除语句在binlog中的大概位置
#切换下二进制日志
mysql >flush logs;
#将二进制binlog文件转换为文本文件
/usr/local/mysql/bin/mysqlbinlog -v --base64-output=DECODE-ROWS ./mysql-bin.000005>temp.log
#找到该操作所对应的事务的开始和结束,然后将日志重定向到另一个文件delete.log
/usr/local/mysql/bin/mysqlbinlog -v --base64-output=DECODE-ROWS --start-position=120 --stop-position=401 ./mysql-bin.000005>delete.log
#使用Python脚本提取恢复insert语句:
python delete.py "./delete.log" 6
#提取出的结果如下:
INSERT INTO `test`.`t1` SELECT ,1 ,'gao' ,'quan' ,31;
INSERT INTO `test`.`t1` SELECT ,2 ,'wang' ,'qua1' ,32;
INSERT INTO `test`.`t1` SELECT ,3 ,'wan' ,'qua1' ,32;
INSERT INTO `test`.`t1` SELECT ,4 ,'qqq' ,'qua1' ,32;
INSERT INTO `test`.`t1` SELECT ,5 ,'qqq' ,'ssss' ,32;
#脚本如下
# -*- coding: utf-8 -*-
import re
#列表拆分
def div_list(ls,n):
n = int(n)
ls_len = len(ls)
j = ls_len/n
ls_return = []
for i in range(0,j):
ls_return.append(ls[i*n:(n*(i+1))])
return ls_return
#col_count为表的列数+2,binlog为mysqlbinlog -v处理过后的文本
def exc_binlog(binlog,col_count):
with open(binlog) as f:
lines=[]
for line in f:
if re.search('###',line):
line=re.sub("\(\d+\)","",re.sub("\@\d+\=",",",line.strip().replace("### "," ").replace("DELETE FROM ","INSERT INTO ").replace("WHERE"," SELECT")))
lines.append(line)
list=div_list(lines,col_count)
with open(r"./copy.log","w") as f:
for i in range(0,len(list)):
list1=list[i]
line=" ".join(list1).replace("SELECT ,","SELECT ")+";"+"\n"
f.writelines(line)
if __name__ == '__main__':
import sys
exc_binlog(sys.argv[1],sys.argv[2])