记一次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

posted @ 2024-07-25 12:23  海yo  阅读(24)  评论(0编辑  收藏  举报