zoukankan      html  css  js  c++  java
  • MySQL【Delete误操作】回滚

    前言:
         
    操作数据库时候难免会因为“大意”而误操作,需要快速恢复的话通过备份来恢复是不太可能的,因为需要还原和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点清楚之后,可以写一个脚本(水平有限,在提升中,写的不好看):

    View Code
    #!/bin/env python
    # -*- encoding: utf-8 -*-
    #-------------------------------------------------------------------------------
    # Name:        restore_insert.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 脚本名 binlog文件 字段数目

    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

    总结:
    下次整理Row和STATEMENT的优劣。   
     

    ~~~~~~~~~~~~~~~ 万物之中,希望至美 ~~~~~~~~~~~~~~~
  • 相关阅读:
    数据库字段太多,批量快速建立实体类方法(适合大量字段建立实体类)
    SQL service 中的 ”输入SQL命令窗口“ 打开了 “属性界面” 回到 ”输入SQL命令窗口“
    计算机软件编程英语词汇集锦
    编程常用英语词汇
    svn上传和下载项目
    当启动tomcat时出现tomcat setting should be set in tomcat preference page
    Implicit super constructor Object() is undefined for default constructor. Must define an explicit constructor
    eclipse中选中一个单词 其他相同的也被选中 怎么设置
    Spring Boot的@SpringBootApplication无法引入的问题
    最全的SpringCloud视频教程
  • 原文地址:https://www.cnblogs.com/zhoujinyi/p/2832543.html
Copyright © 2011-2022 走看看