记一次mysql生产误删表抢救操作
背景
数据库的操作必须要采取一系列的措施来规范流程和管理。然而,不同客户群体管理水平不一,删库跑路也并不是茶余饭后的笑话,它真真实实的,突如其来的就发生在你身边。
接项目经理前线打来电话,某医院突发生产故障,通过业务日志得知,数据库缺表,需要紧急恢复数据,恢复生产。
思路
确认环境和条件
0.已确认生产受影响,关闭应用防止报错业务日志堆积。
1.好端端的生产库怎么可能缺一张至关重要的表,除了人为删除找不到其他合理的解释。
2.恢复数据,肯定是先找最近的备份记录及文件。
3.确认备份策略(mysqldump备份,一天一全备,凌晨1点执行,保留7天备份数据)
4.确认是否有开启binlog(正常生产上线,必须是开着的)
梳理恢复流程
大致分两个步骤:
1.通过全备,建表并恢复表数据到今天凌晨1点。
2.读取binlog日志,恢复从凌晨1点到最后生产故障时间点的数据。(保证这一天下来的增量数据)
具体恢复流程开始
1.通过binlog定位误删操作的时间,命令等信息。
mysqlbinlog -d 数据库名 -v --skip-gtids binlog文件名 |grep 'DROP TABLE' -C 10
通过mysqlbinlog命令,可得:
找到误删操作的时间点:20240724 17:42:52
对应的binlog文件名为:bin.000399
最后故障前的数据库恢复点pos:444959948
操作进程id:thread_id=159424
对方可能是跑了脚本,DROP TABLE IF EXISTS,可能是想在测试库上跑脚本建表,结果执行到了生产,把生产库表删了。
2.确认全备时的点位
凌晨一点备份,对应的binlog文件名为:bin.000396(可以从图片看到396的binlog是从23号的20:00多一直写到24号01:07)
后续捞全备后一天的增量数据,就从bin.000396这个日志开始捞最全,不怕数据重复,顶多插不进去,最怕数据丢失。
3.抽取全备里面的建表语句+表数据,恢复到生产库。(数据最新到凌晨1点)
抽取建表语句
cat {全备sql文件} |grep 'CREATE TABLE `XXXXXXXX`' -A 50 |more
抽取表数据
cat {全备sql文件} |grep 'INSERT INTO `XXXXXXXX`' >> data_insert.sql
建表
通过上面抽取的建表语句,要么直接执行,要么放到create_table.sql文件里,use {db};source /path/to/create_table.sql
锁表
lock tables XXXXXXXX write;
导入全量表数据
use {db};source /path/to/data_insert.sql
或者
/path/to/bin/mysql -h {ip} -P {端口} -u root -p{密码} -S /path/to/tmp/mysql.sock {数据库} < /path/to/data_insert.sql
亦可
通过业务数据确认最新表数据的时间戳
确认最新数据为故障前20240724 01:00:00之前的最新数据
4.利用my2sql,读取binlog,捞取从凌晨1点的数据追到最后生产故障时间点的最新数据。(补充这一天下来的增量数据)
./my2sql -host {服务器ip} -port {端口} -user root -password 'XXXXX' -mode file -work-type 2sql -databases ehc -tables {要恢复的表名} -local-binlog-file ./bin.000396 -start-file bin.000396 -stop-file bin.000399 -start-datetime "2024-07-24 00:40:00" -stop-datetime "2024-07-24 18:00:00" -output-dir ./tmpdir
前提工作
1.my2sql工具传进去(我是直接放到binlog的目录下)
2.确保my2sql可以执行
3.确保开始捞增量的开始和结束的时间点和binlog文件(前面已经确认过了)
3.创建tmpdir文件夹
执行成功后,在tmpdir目录下生成forward.396.sql/forward.397.sql(中间有多少binlog,就会生成多少个sql)
通过head -n 进行sql确认
导入增量数据
/path/to/bin/mysql -h {ip} -P {端口} -u root -p{密码} -S /path/to/tmp/mysql.sock {数据库} < /path/to/forward.396.sql
/path/to/bin/mysql -h {ip} -P {端口} -u root -p{密码} -S /path/to/tmp/mysql.sock {数据库} < /path/to/forward.397.sql
通过业务数据确认最新表数据的时间戳
确认最新数据为故障前20240724 17:42:52之前的最新数据
解锁表
UNLOCK TABLES;
数据恢复结束,确认业务是否恢复。
业务数据再次确认,启动应用,观察应用是否正常,业务拨测,观察数据库数据是否正常。
故障溯源
1.从操作进程id:thread_id=159424出发,SHOW PROCESSLIST或者通过查询information_schema数据库中的PROCESSLIST表来获取类似的信息。
2.结合审计日志。
参考
https://github.com/liuhr/my2sql
https://www.modb.pro/db/464513