MySQL的delete误操作的快速恢复方法

1. 根据误操作时间定位binlog位置
找到数据库的binlog存放位置,当前正在使用的binlog文件里面就有我们要恢复的数据。一般生产环境中的binlog文件都是几百M乃至上G的大小,我们不能逐行去找被删除的数据在什么位置,所以记住误操作的时间很重要,我们可以通过mysqlbinlog命令的--start-datetime参数快速定位数据位置。比如误操作时间为20181104151800,解析出的binlog内容:

[[email protected] mysql]# mysqlbinlog -vv --start-datetime=‘2018-11-04 15:18:00‘ on.000004|more
/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
/*!50003 SET @[email protected]@COMPLETION_TYPE,COMPLETION_TYPE=0*/;
DELIMITER /*!*/;
# at 4
#700101  8:00:00 server id 1  end_log_pos 120 CRC32 0x199f2da4     Start: binlog v 4, server v 5.6.42-log created 700101  8:00:
00
# Warning: this binlog is either in use or was not closed properly.
BINLOG ‘
AAAAAA8BAAAAdAAAAHgAAAABAAQANS42LjQyLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAAXAAEGggAAAAICAgCAAAACgoKGRkAAaQt
nxk=
‘/*!*/;
# at 120
#181104 15:18:37 server id 1  end_log_pos 192 CRC32 0x2224f8de     Query    thread_id=16    exec_time=0    error_code=0
SET TIMESTAMP=1541315917/*!*/;
SET @@session.pseudo_thread_id=16/*!*/;
SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;
SET @@session.sql_mode=1075838976/*!*/;
SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;
/*!\C latin1 *//*!*/;
SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;
SET @@session.lc_time_names=0/*!*/;
SET @@session.collation_database=DEFAULT/*!*/;
BEGIN
/*!*/;
# at 192
#181104 15:18:37 server id 1  end_log_pos 252 CRC32 0x65fbbe3b     Table_map: `test`.`person` mapped to number 85
# at 252
#181104 15:18:37 server id 1  end_log_pos 435 CRC32 0x005d1b39     Delete_rows: table id 85 flags: STMT_END_F

BINLOG ‘
TZ3eWxMBAAAAPAAAAPwAAAAAAFUAAAAAAAEABHRlc3QABnBlcnNvbgAGAw/+DwMDBgoA/gEKAD47
vvtl
TZ3eWyABAAAAtwAAALMBAAAAAFUAAAAAAAEAAgAG/8ABAAAAAmppATEDd2VyqEA0AGpqyADAAgAA
AANsdW8BMQN3ZXKcQjQAJ2zZAMADAAAAAnl1ATAEamVndfombwA3JyEBwAQAAAACZGEBMAdiZWlq
aW5nOgZQAFfZQADABQAAAAJnagEwB2JlaWppbmcSBlAAh+jOAMAGAAAABHlhbmcBMAduYW5qaW5n
cg5MAIdSqwo5G10A
‘/*!*/;
### DELETE FROM `test`.`person`
### WHERE
###   @1=1 /* INT meta=0 nullable=0 is_null=0 */
###   @2=‘ji‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */
###   @3=‘1‘ /* STRING(1) meta=65025 nullable=1 is_null=0 */
###   @4=‘wer‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */
###   @5=3424424 /* INT meta=0 nullable=1 is_null=0 */
###   @6=13134442 /* INT meta=0 nullable=1 is_null=0 */
### DELETE FROM `test`.`person`
### WHERE
###   @1=2 /* INT meta=0 nullable=0 is_null=0 */
###   @2=‘luo‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */
###   @3=‘1‘ /* STRING(1) meta=65025 nullable=1 is_null=0 */
###   @4=‘wer‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */
###   @5=3424924 /* INT meta=0 nullable=1 is_null=0 */
###   @6=14248999 /* INT meta=0 nullable=1 is_null=0 */
### DELETE FROM `test`.`person`
### WHERE
###   @1=3 /* INT meta=0 nullable=0 is_null=0 */
###   @2=‘yu‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */
###   @3=‘0‘ /* STRING(1) meta=65025 nullable=1 is_null=0 */
###   @4=‘jegu‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */
###   @5=7284474 /* INT meta=0 nullable=1 is_null=0 */
###   @6=18949943 /* INT meta=0 nullable=1 is_null=0 */
### DELETE FROM `test`.`person`
### WHERE
###   @1=4 /* INT meta=0 nullable=0 is_null=0 */
###   @2=‘da‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */
###   @3=‘0‘ /* STRING(1) meta=65025 nullable=1 is_null=0 */
###   @4=‘beijing‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */
###   @5=5244474 /* INT meta=0 nullable=1 is_null=0 */
###   @6=4249943 /* INT meta=0 nullable=1 is_null=0 */
### DELETE FROM `test`.`person`
### WHERE
###   @1=5 /* INT meta=0 nullable=0 is_null=0 */
###   @2=‘gj‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */
###   @3=‘0‘ /* STRING(1) meta=65025 nullable=1 is_null=0 */
###   @4=‘beijing‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */
###   @5=5244434 /* INT meta=0 nullable=1 is_null=0 */
###   @6=13559943 /* INT meta=0 nullable=1 is_null=0 */
### DELETE FROM `test`.`person`
### WHERE
###   @1=6 /* INT meta=0 nullable=0 is_null=0 */
###   @2=‘yang‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */
###   @3=‘0‘ /* STRING(1) meta=65025 nullable=1 is_null=0 */
###   @4=‘nanjing‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */
###   @5=4984434 /* INT meta=0 nullable=1 is_null=0 */
###   @6=178999943 /* INT meta=0 nullable=1 is_null=0 */
# at 435
#181104 15:18:37 server id 1  end_log_pos 466 CRC32 0xab85d971     Xid = 197
COMMIT/*!*/;
# at 466
#181104 15:19:38 server id 1  end_log_pos 538 CRC32 0x8b9e1093     Query    thread_id=16    exec_time=0    error_code=0
SET TIMESTAMP=1541315978/*!*/;
BEGIN
/*!*/;
# at 538
#181104 15:19:38 server id 1  end_log_pos 598 CRC32 0xb1679f78     Table_map: `test`.`person` mapped to number 85
# at 598
#181104 15:19:38 server id 1  end_log_pos 656 CRC32 0xa5d7a2d6     Write_rows: table id 85 flags: STMT_END_F

  通过上面的命令可以比较方便地逐页寻找被删除的数据,我们应该要找到被删除的数据在binlog中的起始和终止位置点,例如上面的被删除数据的位置点在192和435之间,这样我们可以保证在这两个位置之间只有我们需要的待恢复的数据,而没有其他数据。

本次测试的数据量很小,如果一张表有数十万行数据被误删除,我们通过上面的方式找位置点是很费时间的。这时可以通过下面的两个命令锁定起始和终止位置:
确定起始位置点:

mysqlbinlog -vv --start-datetime=‘2018-11-04 15:18:00‘ on.000004| head -1000 |more

  确定终止位置点:

mysqlbinlog -vv --start-datetime=‘2018-11-04 15:18:00‘ --stop-datetime=‘2018-11-04 15:20:00‘ on.000004| tail -1000 |more

  我们只看binlog输出的前N行和后N行,来找到起始和终止位置,这样可以大大节省时间。

三、将binlog里的delete语句转化为insert语句
Binlog是二进制文件,我们可以先把待恢复数据导出为可阅读文本:

mysqlbinlog -vv --start-position=192 --stop-position=435 on.000004 |grep ^"###" >/tmp/bin_data

接下来就是处理/tmp/bin_data文本,将里面的delete语句转化为insert语句,可以通过下面的语句实现转化:

cat /tmp/bin_data | sed -n ‘/###/p‘ | sed ‘s/### //g;s/\/\*.*/,/g;s/DELETE FROM/INSERT INTO/g;s/WHERE/SELECT/g;‘ |sed -r ‘s/(@6.*),/\1;/g‘ | sed ‘s/@[1-9]=//g‘ | sed ‘s/@[1-9][0-9]=//g‘ >/tmp/person.sql

四、将insert语句导入数据库中
Delete语句误操作只会删除表数据,而表结构还在。所以我们可以直接将文本里的insert语句导入到数据库中,即可完成数据恢复:

mysql -h127.0.0.1 -P3306 -uroot -p123 < /tmp/person.sql

补充和总结:
1、以上操作只针对delete误操作有效,且binlog模式是行模式;如果是drop或者truncate语句造成的误操作,亦或者binlog不是row模式,在binlog文件里是找不到完整的被删除数据,这个时候可以考虑通过备份进行恢复;
2、如果在误操作很久之后才意识到数据被误删除,记不清误操作的大致时间,那么可以找到误操作所在的binlog文件,将binlog解析为可阅读文本形式,然后借助文本编辑命令找误操作位置,再恢复;如果这种方式很慢的话,可以考虑通过备份恢复,或者从别的环境中导出这张表的数据再导入到当前环境中;
3、Mysqlbinlog命令重要参数
-vv 将二进制转换为可阅读文本
--start-datetime 起始时间
--stop-datetime 终止时间
--start-position 起始位置
--stop-position 终止位置
--base64-output=decode-row 查看最底层DML语句数据模块,前提是数据库参数binlog_rows_query_log_events打开
4、熟悉linux的文本编辑命令,如grep、sed、awk等
5、虽然binlog2sql工具也可以快速解析binlog,生成回滚SQL,但只要清楚上面的命令和操作流程,恢复速度也不会比binlog2sql慢很多,更何况如果环境没有安装这个工具。

  1. [[email protected] mysql]# mysqlbinlog -vv --start-datetime=‘2018-11-04 15:18:00‘ on.000004|more
  2.  

    /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;

  3.  

    /*!40019 SET @@session.max_insert_delayed_threads=0*/;

  4.  

    /*!50003 SET @[email protected]@COMPLETION_TYPE,COMPLETION_TYPE=0*/;

  5.  

    DELIMITER /*!*/;

  6.  

    # at 4

  7.  

    #700101 8:00:00 server id 1 end_log_pos 120 CRC32 0x199f2da4 Start: binlog v 4, server v 5.6.42-log created 700101 8:00:

  8.  

    00

  9.  

    # Warning: this binlog is either in use or was not closed properly.

  10.  

    BINLOG ‘

  11.  

    AAAAAA8BAAAAdAAAAHgAAAABAAQANS42LjQyLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

  12.  

    AAAAAAAAAAAAAAAAAAAAAAAAEzgNAAgAEgAEBAQEEgAAXAAEGggAAAAICAgCAAAACgoKGRkAAaQt

  13.  

    nxk=

  14.  

    ‘/*!*/;

  15.  

    # at 120

  16.  

    #181104 15:18:37 server id 1 end_log_pos 192 CRC32 0x2224f8de Query thread_id=16 exec_time=0 error_code=0

  17.  

    SET TIMESTAMP=1541315917/*!*/;

  18.  

    SET @@session.pseudo_thread_id=16/*!*/;

  19.  

    SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=0, @@session.unique_checks=1, @@session.autocommit=1/*!*/;

  20.  

    SET @@session.sql_mode=1075838976/*!*/;

  21.  

    SET @@session.auto_increment_increment=1, @@session.auto_increment_offset=1/*!*/;

  22.  

    /*!\C latin1 *//*!*/;

  23.  

    SET @@session.character_set_client=8,@@session.collation_connection=8,@@session.collation_server=8/*!*/;

  24.  

    SET @@session.lc_time_names=0/*!*/;

  25.  

    SET @@session.collation_database=DEFAULT/*!*/;

  26.  

    BEGIN

  27.  

    /*!*/;

  28.  

    # at 192

  29.  

    #181104 15:18:37 server id 1 end_log_pos 252 CRC32 0x65fbbe3b Table_map: `test`.`person` mapped to number 85

  30.  

    # at 252

  31.  

    #181104 15:18:37 server id 1 end_log_pos 435 CRC32 0x005d1b39 Delete_rows: table id 85 flags: STMT_END_F

  32.  

  33.  

    BINLOG ‘

  34.  

    TZ3eWxMBAAAAPAAAAPwAAAAAAFUAAAAAAAEABHRlc3QABnBlcnNvbgAGAw/+DwMDBgoA/gEKAD47

  35.  

    vvtl

  36.  

    TZ3eWyABAAAAtwAAALMBAAAAAFUAAAAAAAEAAgAG/8ABAAAAAmppATEDd2VyqEA0AGpqyADAAgAA

  37.  

    AANsdW8BMQN3ZXKcQjQAJ2zZAMADAAAAAnl1ATAEamVndfombwA3JyEBwAQAAAACZGEBMAdiZWlq

  38.  

    aW5nOgZQAFfZQADABQAAAAJnagEwB2JlaWppbmcSBlAAh+jOAMAGAAAABHlhbmcBMAduYW5qaW5n

  39.  

    cg5MAIdSqwo5G10A

  40.  

    ‘/*!*/;

  41.  

    ### DELETE FROM `test`.`person`

  42.  

    ### WHERE

  43.  

    ### @1=1 /* INT meta=0 nullable=0 is_null=0 */

  44.  

    ### @2=‘ji‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */

  45.  

    ### @3=‘1‘ /* STRING(1) meta=65025 nullable=1 is_null=0 */

  46.  

    ### @4=‘wer‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */

  47.  

    ### @5=3424424 /* INT meta=0 nullable=1 is_null=0 */

  48.  

    ### @6=13134442 /* INT meta=0 nullable=1 is_null=0 */

  49.  

    ### DELETE FROM `test`.`person`

  50.  

    ### WHERE

  51.  

    ### @1=2 /* INT meta=0 nullable=0 is_null=0 */

  52.  

    ### @2=‘luo‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */

  53.  

    ### @3=‘1‘ /* STRING(1) meta=65025 nullable=1 is_null=0 */

  54.  

    ### @4=‘wer‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */

  55.  

    ### @5=3424924 /* INT meta=0 nullable=1 is_null=0 */

  56.  

    ### @6=14248999 /* INT meta=0 nullable=1 is_null=0 */

  57.  

    ### DELETE FROM `test`.`person`

  58.  

    ### WHERE

  59.  

    ### @1=3 /* INT meta=0 nullable=0 is_null=0 */

  60.  

    ### @2=‘yu‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */

  61.  

    ### @3=‘0‘ /* STRING(1) meta=65025 nullable=1 is_null=0 */

  62.  

    ### @4=‘jegu‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */

  63.  

    ### @5=7284474 /* INT meta=0 nullable=1 is_null=0 */

  64.  

    ### @6=18949943 /* INT meta=0 nullable=1 is_null=0 */

  65.  

    ### DELETE FROM `test`.`person`

  66.  

    ### WHERE

  67.  

    ### @1=4 /* INT meta=0 nullable=0 is_null=0 */

  68.  

    ### @2=‘da‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */

  69.  

    ### @3=‘0‘ /* STRING(1) meta=65025 nullable=1 is_null=0 */

  70.  

    ### @4=‘beijing‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */

  71.  

    ### @5=5244474 /* INT meta=0 nullable=1 is_null=0 */

  72.  

    ### @6=4249943 /* INT meta=0 nullable=1 is_null=0 */

  73.  

    ### DELETE FROM `test`.`person`

  74.  

    ### WHERE

  75.  

    ### @1=5 /* INT meta=0 nullable=0 is_null=0 */

  76.  

    ### @2=‘gj‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */

  77.  

    ### @3=‘0‘ /* STRING(1) meta=65025 nullable=1 is_null=0 */

  78.  

    ### @4=‘beijing‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */

  79.  

    ### @5=5244434 /* INT meta=0 nullable=1 is_null=0 */

  80.  

    ### @6=13559943 /* INT meta=0 nullable=1 is_null=0 */

  81.  

    ### DELETE FROM `test`.`person`

  82.  

    ### WHERE

  83.  

    ### @1=6 /* INT meta=0 nullable=0 is_null=0 */

  84.  

    ### @2=‘yang‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */

  85.  

    ### @3=‘0‘ /* STRING(1) meta=65025 nullable=1 is_null=0 */

  86.  

    ### @4=‘nanjing‘ /* VARSTRING(10) meta=10 nullable=1 is_null=0 */

  87.  

    ### @5=4984434 /* INT meta=0 nullable=1 is_null=0 */

  88.  

    ### @6=178999943 /* INT meta=0 nullable=1 is_null=0 */

  89.  

    # at 435

  90.  

    #181104 15:18:37 server id 1 end_log_pos 466 CRC32 0xab85d971 Xid = 197

  91.  

    COMMIT/*!*/;

  92.  

    # at 466

  93.  

    #181104 15:19:38 server id 1 end_log_pos 538 CRC32 0x8b9e1093 Query thread_id=16 exec_time=0 error_code=0

  94.  

    SET TIMESTAMP=1541315978/*!*/;

  95.  

    BEGIN

  96.  

    /*!*/;

  97.  

    # at 538

  98.  

    #181104 15:19:38 server id 1 end_log_pos 598 CRC32 0xb1679f78 Table_map: `test`.`person` mapped to number 85

  99.  

    # at 598

  100.  

    #181104 15:19:38 server id 1 end_log_pos 656 CRC32 0xa5d7a2d6 Write_rows: table id 85 flags: STMT_END_F

原文地址:https://www.cnblogs.com/xiaozengzeng/p/12078067.html

时间: 2024-10-13 05:23:22

MySQL的delete误操作的快速恢复方法的相关文章

MySQL【Update误操作】回滚(转)

前言:      继上一篇MySQL[Delete误操作]回滚之后,现在介绍下Update回滚,操作数据库时候难免会因为“大意”而误操作,需要快速恢复的话通过备份来恢复是不太可能的,因为需要还原和binlog差来恢复,等不了,很费时.这里说明因为Update 操作的恢复方法:主要还是通过binlog来进行恢复,前提是binlog_format必须是Row格式,否则只能通过备份来恢复数据了.和上一篇的条件一样.方法:     条件:开启Binlog,Format为Row.     步骤:1.通过M

mysql权限的误操作的恢复

mysql权限的误操作的恢复 原因:由于误操作,我把repl用户授予了所有权限,但删除了数据库中的其他用户及权限,因此repl用户虽然具有操作所有数据库的权限,但没有grant权限,所以若想授予其他用户权限,来管理数据库,出现这种状况就酷毙了,没有授予权限怎麽办? 误操作过程: mysql >grant all on *.* to 'repl'@'192.168.1.%' identified by '123456'; mysql> flush privileges; 授予完以后,我把其他的所

SQLServer 2008以上误操作数据库恢复方法——日志尾部备份

问题: 经常看到有人误删数据,或者误操作,特别是update和delete的时候没有加where,然后就喊爹喊娘了.人非圣贤孰能无过,做错可以理解,但不能纵容,这个以后再说,现在先来解决问题. 遇到这种情况,一般都是没有做备份,不然也不会来发问了.首先要冷静,否则会有更大的灾难.直到你放弃. 解决方法: 对于这类问题,主要是找回误操作之前的数据,在2008之前,有个很出名的工具Log Exploer,听说还挺好用的,这个网上大把教程,这里就不多说了.但是唯一遗憾的是,不支持2008及更高版本,这

【转】SQLServer 2008以上误操作数据库恢复方法——日志尾部备份

4号,公司的生产数据表被全部删除,目前没有找到原因,由于刚接触SQL不久,所以短时间内不会还原,也不敢动被原服务器,于是就将原服务器停掉,拷贝出里面的PPD数据库文件,留作备份:近几天在自己的电脑上尝试修复,一直没有成功,细读了一下<SQL2005技术内幕——存储引擎>了解到删除列.删除表这些操作不会直接对每一行数据进行操作,而是直接改变他们的物理指向地址的ID,专业术语我也不是很清楚,我的理解是这样的,有时间再弄清楚,不过这足以让我明白被删除的表还是存在mdf文件中,其改变的便宜地址记录在日

Linux系统目录权限chmod误操作权限修复方法

Linux中,如果意外误操作将/目录权限批量设置,比如chmod -R 777 / ,系统中的大部分服务以及命令将无法使用,这时候可以通过系统自带的getfacl命令来拷贝和还原系统权限,若是其他系统目录被误操作,同样可行.修复的方法如下: 1.通过一台权限正常的Linux(最好内核版本和故障服务器相同) getfacl -R / >systemp.bak 2.如果异常服务器未重启等操作并且连接未端,可以使用scp命令将正常的备份文件传至异常服务器中,命令如下: scp [email prote

MySQL之delete 忘加where条件误删除恢复方法二

和昨天介绍的MySQL之delete 忘加where条件误删除恢复的mysql的环境条件是一样的:mysql数据库指定字符集位utf8,同时表的字符集也得为utf8,同时mysql要开启row模式的bin-log日志 创建一张测试表测试: create table MyClass( id int(4) not null primary key auto_increment, name char(20) not null, sex varchar(10) not null default '0',

MySQL之delete 忘加where条件误删除恢复

一.mysql环境介绍: mysql数据库指定字符集位utf8,同时表的字符集也得为utf8,同时mysql要开启row模式的bin-log日志 /etc/my.cnf文件字符集参数设置: [[email protected] ~]# grep character-set /etc/my.cnf [client] port = 3306 socket = /tmp/mysql.sock default-character-set=utf8 [mysqld] port = 3306 socket

mysql 的delete from 和update子查询限制

最经做项目时发现的问题,好像在update时也有... 网上查到的资料如下: 1.使用mysql进行delete from操作时,若子查询的 FROM 字句和更新/删除对象使用同一张表,会出现错误. mysql> DELETE FROM tab1 WHERE col1 = ( SELECT MAX( col1 ) FROM tab1 ); ERROR 1093 (HY000): You can't specify target table 'tab1′ for update in FROM cl

MySQL 误操作后如何快速恢复数据~!~!~

基本上每个跟数据库打交道的程序员(当然也可能是你同事)都会碰一个问题,MySQL误操作后如何快速回滚?比如,delete一张表,忘加限制条件,整张表没了.假如这还是线上环境核心业务数据,那这事就闹大了.误操作后,能快速回滚数据是非常重要的. 传统解法 用全量备份重搭实例,再利用增量binlog备份,恢复到误操作之前的状态.然后跳过误操作的SQL,再继续应用binlog.此法费时费力,不值得再推荐. 利用binlog2sql快速闪回 首先,确认你的MySQL server开启了binlog,设置了