>데이터 베이스 >MySQL 튜토리얼 >实现MySQL回滚的Python脚本的编写教程_MySQL

实现MySQL回滚的Python脚本的编写教程_MySQL

PHP中文网
PHP中文网원래의
2016-05-27 13:45:481562검색

操作数据库时候难免会因为“大意”而误操作,需要快速恢复的话通过备份来恢复是不太可能的,因为需要还原和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 &#39;&#39;.join(lines).find(&#39;@&#39;) <> -1 and lines[3].split(&#39;=&#39;,1)[0] <> num:     
      #num为列数,要是小于最大的列数,后面均加, 
        lines[3] = lines[3].split(&#39;=&#39;,1)[-1].strip() 
        if lines[3].strip(&#39;\&#39;&#39;).strip().find(&#39;\&#39;&#39;) <> -1: 
          lines[3] = lines[3].split(&#39;/*&#39;)[0].strip(&#39;\&#39;&#39;).strip().strip(&#39;\&#39;&#39;).replace(&#39;\\&#39;,&#39;&#39;).
          replace(&#39;\&#39;&#39;,&#39;\\\&#39;&#39;) #这里过滤掉转义的字符串 
          lines[3] = &#39;\&#39;&#39; + lines[3] + &#39;\&#39;,&#39; 
        elif lines[3].find(&#39;INT meta&#39;) <> -1:        #过滤Int类型的字段为负数后带的(),正数不受影响 
          lines[3] = lines[3].split(&#39;/*&#39;)[0].strip() 
          lines[3] = lines[3].split()[0] + &#39;,&#39; 
        elif lines[3].find(&#39;NULL&#39;) <> -1: 
          lines[3] = lines[3].split(&#39;/*&#39;)[0].strip() 
          lines[3] = lines[3] + &#39;,&#39; 
        else: 
          lines[3] = lines[3].split(&#39;/*&#39;)[0].strip(&#39;\&#39;&#39;).strip().strip(&#39;\&#39;&#39;).replace(&#39;\\&#39;,&#39;&#39;).
          replace(&#39;\&#39;&#39;,&#39;\\\&#39;&#39;) #这里过滤掉转义的字符串 
          lines[3] = &#39;\&#39;&#39; + lines[3].strip(&#39;\&#39;&#39;&#39; &#39;) + &#39;\&#39;,&#39; 
      if &#39;&#39;.join(lines).find(&#39;@&#39;) <> -1 and lines[3].split(&#39;=&#39;,1)[0] == num:     
      #num为列数,要是小于最大的列数,后面均加); 
        lines[3] = lines[3].split(&#39;=&#39;,1)[-1].strip() 
        if lines[3].find(&#39;\&#39;&#39;) <> -1: 
          lines[3] = lines[3].split(&#39;/*&#39;)[0].strip(&#39;\&#39;&#39;).strip().strip(&#39;\&#39;&#39;).replace(&#39;\\&#39;,&#39;&#39;).
          replace(&#39;\&#39;&#39;,&#39;\\\&#39;&#39;) #同上 
          lines[3] = &#39;\&#39;&#39; + lines[3] + &#39;\&#39;);&#39; 
        elif lines[3].find(&#39;INT meta&#39;) <> -1:        #同上 
          lines[3] = lines[3].split(&#39;/*&#39;)[0].strip() 
          lines[3] = lines[3].split(&#39; &#39;)[0] + &#39;);&#39; 
        elif lines[3].find(&#39;NULL&#39;) <> -1: 
          lines[3] = lines[3].split(&#39;/*&#39;)[0].strip() 
          lines[3] = lines[3] + &#39;);&#39; 
        else: 
          lines[3] = lines[3].split(&#39;/*&#39;)[0].strip(&#39;\&#39;&#39;).strip().strip(&#39;\&#39;&#39;).replace(&#39;\\&#39;,&#39;&#39;).
          replace(&#39;\&#39;&#39;,&#39;\\\&#39;&#39;) #同上 
          lines[3] = &#39;\&#39;&#39; + lines[3].strip(&#39;\&#39;&#39;&#39; &#39;) + &#39;\&#39;);&#39; 
      print &#39; &#39;.join(lines[1:]) 
    if lines == &#39;&#39;: 
      break 
if __name__ == &#39;__main__&#39;: 
  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, 
 &#39;1990:11:12&#39;, 
 NULL, 
 2, 
 &#39;&#39;, 
 0, 
 &#39;&#39;, 
 -1, 
 0, 
 340800, 
 1, 
 0, 
 &#39;&#39;, 
…… 
…… 
 1, 
 NULL 
);

最后还原:

mysql test < binlog.sql


以上就是实现MySQL回滚的Python脚本的编写教程_MySQL的内容,更多相关内容请关注PHP中文网(www.php.cn)!


성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.