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