场景:某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])