凌晨两点四十七分,手机震了,值班群里的消息一条接一条。不用看也知道:有人在生产库上执行了 UPDATE 忘了带 WHERE,或者 DELETE 条件写错,再干脆一点,直接 DROP TABLE 手滑。干这行的人一听到"删库"两个字,脑子里蹦出来的第一个念头往往是"跑路"。
但说句实在话,只要你的 binlog 配置没偷懒,绝大多数 DML 误操作都能靠 binlog2sql 这把"后悔药"原样翻回来。这篇文章就从一个一线 DBA 的角度,把 binlog2sql 的原理、实操、踩坑和边界一次讲透。适合正在值班的后端开发、身兼数职的兼职运维、以及所有被授权摸过生产库的人。看完你至少能回答一个问题:真到了删库那一刻,除了跑路,我还能干什么。
1. 事故现场:先别提交离职信,按这五条判断还有没有救
1.1 第一件事不是查日志,而是把写入冻结
误删发生后的第一个动作,很多人的本能是马上去翻 binlog、去导数据、去查日志,这个顺序其实是错的。正确的顺序是:先让业务写入停住。
原因很简单:binlog2sql 回滚的本质是"把误操作对应的旧数据重新写回去"。如果你在回滚的同时,业务还在继续对同一张表做 INSERT 和 UPDATE,那么回滚 SQL 执行时大概率会和这些新数据打架——要么主键冲突,要么把别人刚改好的数据覆盖掉,最后现场越搞越乱。
所以确认误操作的第一时间,除非你能接受这张表丢失几分钟甚至几十分钟的业务写入,否则建议直接停服、停接口,或者对该表加读锁:
sql复制LOCK TABLES orders READ;
先把数据面冻结住,再开始评估损失。很多人舍不得停那几分钟,结果多花了一整夜去擦屁股,这笔账怎么算都不划算。
1.2 五连问:能救不能救,全靠这几个开关
接下来,快速回答下面几个问题。任何一个不满足,回滚方案都要换打法:
| 检查项 | 要求 | 不满足的后果 |
|---|---|---|
| log_bin 是否开启 | ON | 没开 binlog,DML 误删只能靠备份,备份也没有就只能跑路了 |
| binlog_format | ROW | STATEMENT 格式不记录行级前后镜像,binlog2sql 解析不出原始行的数据 |
| binlog_row_image | FULL(MySQL 5.6+) | MINIMAL 时只记录变更列,回滚 SQL 缺字段,无法完整恢复 |
| binlog 保留时间 | 覆盖误操作时刻 | 误删在 3 天前,binlog 只留 2 天,数据早被 purge 了 |
| 事故类型 | DML 可闪回;DDL 另有方案 | 见 1.3 |
检查命令直接抄:
sql复制SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'binlog_format';
SHOW VARIABLES LIKE 'binlog_row_image';
SHOW VARIABLES LIKE 'binlog_expire_logs_seconds';
SHOW BINARY LOGS;
如果结论是前三项全都满足,恭喜,你手里有牌可打。如果 log_bin 是 OFF,或者 binlog_format 还是 STATEMENT,那 binlog2sql 这条路基本断了,接下来只能去翻备份,翻不到的话,就真的只能评估损失、走事后复盘流程了。
1.3 分清 DML 和 DDL:binlog2sql 救不了 DROP TABLE
这里必须把话说清楚:binlog2sql 不是万能的,它救的是 DML,救不了 DDL。
- UPDATE 忘带 WHERE、DELETE 条件写错、INSERT 插错数据,这类 DML 误操作,只要 binlog
