实现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