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的优劣。   
     

    ~~~~~~~~~~~~~~~ 万物之中,希望至美 ~~~~~~~~~~~~~~~
  • 相关阅读:
    什么是ORM
    ORM优缺点
    Azure 中快速搭建 FTPS 服务
    连接到 Azure 上的 SQL Server 虚拟机(经典部署)
    在 Azure 虚拟机中配置 Always On 可用性组(经典)
    SQL Server 2014 虚拟机的自动备份 (Resource Manager)
    Azure 虚拟机上的 SQL Server 常见问题
    排查在 Azure 中新建 Windows 虚拟机时遇到的经典部署问题
    上传通用化 VHD 并使用它在 Azure 中创建新 VM
    排查在 Azure 中新建 Windows VM 时遇到的部署问题
  • 原文地址:https://www.cnblogs.com/zhoujinyi/p/2832543.html
Copyright © 2011-2022 走看看