能找回,但前提是binlog必须开着、格式是row、且binlog_row_image设为full;缺一不可,否则binlog2sql生成的回滚sql会缺失字段或含null,导致数据不一致。

能找回,但前提是 binlog 必须开着、格式是 ROW、且 binlog_row_image 设为 FULL。缺任何一条,就可能只能恢复部分字段,甚至完全无法还原。
确认 binlog 是否满足回滚前提
不是所有 binlog 都能反向还原 UPDATE。关键看三件事:
-
log_bin变量值必须为ON(SHOW VARIABLES LIKE 'log_bin';) -
binlog_format必须是ROW(SHOW VARIABLES LIKE 'binlog_format';) -
binlog_row_image必须是FULL(SHOW VARIABLES LIKE 'binlog_row_image';),否则旧值只记被改字段,其他字段为空,拼不出完整原行
如果其中任意一项不满足,binlog2sql 或 mysqlbinlog 解析出的 SQL 会出现 NULL 值或缺失字段,执行后数据不一致。
用 binlog2sql 生成回滚 SQL
这是最常用、最可控的方式,适合线上快速定位和生成可验证语句:
- 安装只需
pip install pymysql,无需编译,Python 2.7+ 即可运行 - 核心命令必须带
-B参数:python binlog2sql.py -h127.0.0.1 -uuser -p'pass' -dmydb -tmytable --start-datetime "2026-09-30 09:50:00" --stop-datetime "2026-09-30 09:52:00" -B - 时间范围要略宽于误操作发生窗口——太窄会漏掉,太宽可能混入其他变更
- 输出每条形如:
UPDATE mytable SET col1='old_val', col2='old_val2' WHERE id=123;,其中old_val来自 binlog 的 pre-image - 注意检查是否含
SET SQL_LOG_BIN=0;——线上执行时务必保留它,否则会二次写入 binlog
执行前必须做隔离与验证
生成的 SQL 看起来“正确”,不等于能直接上线:
- 先在测试库导入当前表快照:
mysqldump -t mydb mytable > snapshot.sql,再应用回滚 SQL,确认数据回到预期状态 - 线上执行前:停掉应用写入,或对目标表加读锁:
FLUSH TABLES WITH READ LOCK; - 别用
source一次性导入大 SQL;拆成 100–500 行一批,每批后SELECT COUNT(*)或抽样校验,防止错一条全错 - 表必须有主键或唯一键;
binlog2sql依赖主键构造WHERE条件,无主键表无法安全还原
为什么不能直接用 mysqlbinlog + sed?
有人用 mysqlbinlog 解析后手工 sed 替换生成 SQL,这在小表、UTF8 字符集、无特殊字符时可行,但风险极高:
-
mysqlbinlog输出的是伪 SQL,不是真正可执行语句,字段顺序、NULL 处理、转义字符(比如单引号、反斜杠)极易出错 - 中文乱码常见于表/库字符集与
mysqlbinlog默认编码不一致,即使显示正常,插入时也可能报错 - 无法自动提取 pre-image,得手动比对前后镜像,效率低且易漏
- 没有
-B这样的语义开关,容易误输出正向语句而非回滚语句
真正线上抢救时,没人敢靠 sed 拼出来的 SQL 救命——差一个引号,整张表就废了。











