前言

题主于今天(2022年11月27日) 在线上环境误操作删除了记录,且没有备份数据,通宵排查事故原因,终于没有酿成生产事故。谨以此文记录。

参考资料

本文是对上文操作的实际补充说明。

1 查看binlog日志

首先确保你binlog日志是打开的。一般线上环境都会打开。命令如下:

show VARIABLES like '%log_bin%';

然后登陆你存放MySQL的服务器。找到存放binlog日志的文件夹。一般项目组运维会知道该文件位置。找到之后会发现非常多的日志文件,如下图:

mysql 误删回滚 mysql恢复误删数据_mysql 误删回滚


注意,最后一个日志文件是实时增量更新的。一直会写入该文件。如果是你近期删除的,直接找上图圈出的文件即可。如果是其它时间段删除的,就找日期命名的文件。

恢复数据时间越早越快越好。我们服务器上只保管45天的记录!

2 找到对应binlog文件,直接执行命令

下面的sql给了个时间段。是你抓取误操作的大致时间段。

mysqlbinlog --no-defaults --start-datetime='2022-10-12 15:00:00' --stop-datetime='2022-10-12 17:00:00' /var/lib/mysql/mysql-bin.000031 >/var/lib/mysql/mysql_delete20221012.sql

执行完毕后,会生成一个sql文件。上面有你全部误操作的数据,(数据经过加密了)里面有非常多的记录,我们只需要找到开始的 index 和 结束的index 即可。

推荐使用 head -100 ; 和 tail -100 来查看开始和结束的结点。找到这两个结果值,记录下:

332334767

366250788

随后执行下面命令, 通过节点精确导出误操作的sql :

mysqlbinlog --no-defaults -vv --start-position=332334767 --stop-position=366250788 /var/lib/mysql/mysql-bin.000031 >/var/lib/mysql/bin_data.sql

其实就是拼接你的时间段。会把所有INSERT,UPDATE语句全部抓出(如下图图例):

mysql 误删回滚 mysql恢复误删数据_mysql 误删回滚_02

3 找到你误删的数据

一般来说你误删的数据会大致记下来一个标识。我这里是单据号。我隐约记得被删除的数据的单据编码是多少,那么我们就可以模糊搜索该条件:

less bin_data.sql | grep -C 100 "单据编号xxxxx"

这样就能得到对应的反向INSERT语句了,如下所示:

mysql 误删回滚 mysql恢复误删数据_数据库_03

4 将delete语句转换成insert语句

可以自行百度,也可以参考下面命令:

cat /var/lib/mysql/bin_data.sql | sed -n '/###/p' | sed 's/### //g;s/\/\*.*/,/g;s/DELETE FROM/INSERT INTO/g;s/WHERE/SELECT/g;' |sed -r 's/(@17.*),/\1;/g' | sed 's/@[1-9]=//g' | sed 's/@[1-9][0-9]=//g' >  /var/lib/mysql/delete2insert.sql

需要注意要符合语法格式。你得自己手工改改,但是大同小异就是了。需要在文件中手动改一些,;之类的符号。


完成

引以为戒!