Welcome

首页 / 数据库 / MySQL / 实现MySQL回滚的Python脚本的编写教程

操作数据库时候难免会因为“大意”而误操作,需要快速恢复的话通过备份来恢复是不太可能的,因为需要还原和binlog差来恢复,等不了,很费时。这里先说明下因为Delete 操作的恢复方法:主要还是通过binlog来进行恢复,前提是binlog_format必须是Row格式,否则只能通过备份来恢复数据了。
方法:
条件:开启Binlog,Format为Row。
步骤:
1.通过MySQL自带工具mysqlbinlog 指定导出操作的记录:
mysqlbinlog --no-defaults --start-datetime="2012-12-25 14:56:00" --stop-datetime="2012-12-25 14:57:00" -vv mysql-bin.000001 > /home/zhoujy/restore/binlog.txt 
2.数据取出来之后,需要把数据解析反转,原始数据:
### DELETE FROM test.me_info ### WHERE ###@1=2165974 /* INT meta=0 nullable=0 is_null=0 */ ###@2="1984:03:17" /* DATE meta=0 nullable=1 is_null=0 */ ###@3=NULL /* DATE meta=765 nullable=1 is_null=1 */ ###@4=2012-10-25 00:00:00 /* DATETIME meta=0 nullable=0 is_null=0 */ ###@5="" /* VARSTRING(765) meta=765 nullable=1 is_null=0 */ ###@6=0 /* TINYINT meta=0 nullable=1 is_null=0 */ ###@7="" /* VARSTRING(765) meta=765 nullable=1 is_null=0 */ ###@8=-1 (4294967295) /* INT meta=0 nullable=1 is_null=0 */ ###@9=0 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ ###@10=NULL /* MEDIUMINT meta=0 nullable=1 is_null=1 */ ###@11=2 /* TINYINT meta=0 nullable=1 is_null=0 */ ###@12=0 /* TINYINT meta=0 nullable=1 is_null=0 */ ###@13="" /* VARSTRING(765) meta=765 nullable=1 is_null=0 */ ###@14="" /* VARSTRING(765) meta=765 nullable=1 is_null=0 */ ###@15=0 /* MEDIUMINT meta=0 nullable=1 is_null=0 */ ###@16=320 /* INT meta=0 nullable=1 is_null=0 */ …………………… …………………… …………………… 
Row格式的binlog记录的格式如上面所示,需要做的工作就是吧Delete的操作转换成Insert操作,发上面的都是有一定规律的,并且需要注意的是:
1、字段类型 DATETIME 日期。在日志中保存的格式为 @4=2012-10-25 00:00:00,需要将2012-10-25 00:00:00加上引号。
2、负数。在日志中保存的格式为 @1=-1 (4294967295), -2(4294967294),-3(4294967293),需要将()里面的数据去掉,只保留@1=-1。
3、转义字符集。如:"s,,等。
上面3点清楚之后,可以写一个脚本(水平有限,在提升中,写的不好看):
#!/bin/env python # -*- encoding: utf-8 -*- #------------------------------------------------------------------------------- # Name:restore.py # Purpose: 通过Binlog恢复Delete误操作数据 # Author: zhoujy # Created: 2012-12-25 # update: 2012-12-25 # Copyright:(c) Mablevi 2012 # Licence: zjy #------------------------------------------------------------------------------- def read_binlog(file,column_num): f=open(file) num = "@"+str(column_num) while True: lines = f.readline() if lines.strip()[0:3] == "###": lines=lines.split(" ",3) if lines[1] == "DELETE" and lines[2] =="FROM":#该部分替换Delete为Insert lines[1] = "INSERT" lines[2] = "INTO" lines[-1] = lines[-1].strip() if lines[1].strip() == "WHERE": lines[1] = "VALUES (" if "".join(lines).find("@") <> -1 and lines[3].split("=",1)[0] <> num: #num为列数,要是小于最大的列数,后面均加, lines[3] = lines[3].split("=",1)[-1].strip() if lines[3].strip(""").strip().find(""") <> -1: lines[3] = lines[3].split("/*")[0].strip(""").strip().strip(""").replace("\","").replace(""","\"") #这里过滤掉转义的字符串 lines[3] = """ + lines[3] + ""," elif lines[3].find("INT meta") <> -1:#过滤Int类型的字段为负数后带的(),正数不受影响 lines[3] = lines[3].split("/*")[0].strip() lines[3] = lines[3].split()[0] + "," elif lines[3].find("NULL") <> -1: lines[3] = lines[3].split("/*")[0].strip() lines[3] = lines[3] + "," else: lines[3] = lines[3].split("/*")[0].strip(""").strip().strip(""").replace("\","").replace(""","\"") #这里过滤掉转义的字符串 lines[3] = """ + lines[3].strip("""" ") + ""," if "".join(lines).find("@") <> -1 and lines[3].split("=",1)[0] == num: #num为列数,要是小于最大的列数,后面均加); lines[3] = lines[3].split("=",1)[-1].strip() if lines[3].find(""") <> -1: lines[3] = lines[3].split("/*")[0].strip(""").strip().strip(""").replace("\","").replace(""","\"") #同上 lines[3] = """ + lines[3] + "");" elif lines[3].find("INT meta") <> -1:#同上 lines[3] = lines[3].split("/*")[0].strip() lines[3] = lines[3].split(" ")[0] + ");" elif lines[3].find("NULL") <> -1: lines[3] = lines[3].split("/*")[0].strip() lines[3] = lines[3] + ");" else: lines[3] = lines[3].split("/*")[0].strip(""").strip().strip(""").replace("\","").replace(""","\"") #同上 lines[3] = """ + lines[3].strip("""" ") + "");" print " ".join(lines[1:]) if lines == "": break if __name__ == "__main__": import sys read_binlog(sys.argv[1],sys.argv[2]) 
执行脚本:
python restore.py binlog.txt 36 > binlog.sql
命令行中的36 表示 需要还原的表的字段有36个,效果:
INSERT INTO test.me_info VALUES (2123269,"1990:11:12",NULL,2,"",0,"",-1,0,340800,1,0,"", …… ……1,NULL ); 
最后还原:
mysql test < binlog.sql