前言
题主于今天(2022年11月27日) 在线上环境误操作删除了记录,且没有备份数据,通宵排查事故原因,终于没有酿成生产事故。谨以此文记录。
参考资料
本文是对上文操作的实际补充说明。
1 查看binlog日志
首先确保你binlog日志是打开的。一般线上环境都会打开。命令如下:
show VARIABLES like '%log_bin%';
然后登陆你存放MySQL的服务器。找到存放binlog日志的文件夹。一般项目组运维会知道该文件位置。找到之后会发现非常多的日志文件,如下图:
注意,最后一个日志文件是实时增量更新的。一直会写入该文件。如果是你近期删除的,直接找上图圈出的文件即可。如果是其它时间段删除的,就找日期命名的文件。
恢复数据时间越早越快越好。我们服务器上只保管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语句全部抓出(如下图图例):
3 找到你误删的数据
一般来说你误删的数据会大致记下来一个标识。我这里是单据号。我隐约记得被删除的数据的单据编码是多少,那么我们就可以模糊搜索该条件:
less bin_data.sql | grep -C 100 "单据编号xxxxx"
这样就能得到对应的反向INSERT语句了,如下所示:
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
需要注意要符合语法格式。你得自己手工改改,但是大同小异就是了。需要在文件中手动改一些,;之类的符号。
完成
引以为戒!