昨天的事情,同事让我删除某条数据,我使用了上下键,没有注意那张表,直接把后面的条件删掉,加上分号,回车了。。。。啊。。。。


幸亏数据不是很多,有备份数据,但是那样回复太慢了。另辟蹊跷,这个也是跟别人学得。下面开始。。


先把binlog考到一个临时的目录,如果没有记录操作前的pos,只能手动找了,说个笨方法,根据执行的命令查看一下这条命令的位置

 

 mysqlbinlog -vv --base64-output=DECODE-ROWS binlog-mysql-7.000007 | grep -n "DELETE FROM `test`.`tt`"

179298:### DELETE FROM `test`.`tt`



然后看好以下这个位置前面的若干行;

DELIMITER /*!*/;

# at 4

#140520 14:03:53 server id 1  end_log_pos 106 Start: binlog v 4, server v 5.1.73-log created 140520 14:03:53 at startup

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

ROLLBACK/*!*/;

BINLOG '

SfB6Uw8BAAAAZgAAAGoAAAABAAQANS4xLjczLWxvZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

AAAAAAAAAAAAAAAAAABJ8HpTEzgNAAgAEgAEBAQEEgAAUwAEGggAAAAICAgC

'/*!*/;

# at 1553209

# at 1553259

# at 1554274

# at 1555289

# at 1556304

# at 1557319


就是这个位置。pos=1559972


或者直接用前面的那个179298 ,直接

 mysqlbinlog -vv binlog-mysql-7.000007 | sed -n '217175,$p'


这里还需要注意的是,这个文件结尾是不是自己需要的,因为数据库在你cp的时候很有可能还会写数据。。。


mysqlbinlog -vv --base64-output=DECODE-ROWS binlog-mysql-7.000007 | sed -n '179298,$p'| sed 's/^### //g;s/^#.*//g;s/COMMIT.*//g;s/DELIMITER.*//g;s/ROLLBACK.*//g;s#/.*[/;]$##g'


这个就是把那些和SQL语句不想管的全部都替换掉。

DELETE FROM `test`.`tt`

WHERE

  @1=221 

  @2=222 

  @3='BZ001117' 

  @4=0 

  @5=NULL 

  @6=0 

  @7=0 

  @8=NULL

类似于这样的SQL了。接下来你该知道怎么做了吧。

接着上面那条命令继续

后面就是把这个SQL换成insert into。


mysqlbinlog -vv --base64-output=DECODE-ROWS binlog-mysql-7.000007 | sed -n '179298,$p'| sed 's/^### //g;s/^#.*//g;s/COMMIT.*//g;s/DELIMITER.*//g;s/ROLLBACK.*//g;s#/.*[/;]$##g;s/`//g;s/DELETE FROM/INSERT INTO /g;s/WHERE/VALUES /g;s/\(VALUES\)/\1(/g;s/\(@[1-7]=\)\(.*\)/\2,/g;s/\(@.=\)\(.*\)/\2);/g' >2.sql


结果是这样子,

INSERT INTO  test.tt

VALUES( 

  221 ,

  222 ,

  'BZ001117' ,

  0 ,

  NULL ,

  0 ,

  0 ,

  NULL );


好像可以了,那就试试

mysql> select count(*) from tt;

+----------+

| count(*) |

+----------+

|      221 |

+----------+

1 row in set (0.00 sec)


果然OK


解决问题了,最后说的是,任何操作头脑要清楚,不要盲目,看清楚在执行。


这个我感觉是最快的恢复误删除的方法。