闪回必须基于主库原始binlog,不能用从库relay-log;需确认主库log_bin=ON、binlog_format=ROW、binlog_row_image=full;推荐用my2sql离线解析生成回滚SQL,并注意起点位置、外键、主键及字符集问题。

主从环境里闪回必须用主库 binlog,不能直接读从库日志
从库的 relay-log 是主库 binlog 的中转副本,不带原始事务上下文(比如 BEGIN/COMMIT 标记),也无法保证 binlog_row_image=full 等关键配置生效。所有闪回操作必须基于主库生成的原始 binlog 文件——哪怕你只能连上从库,也得把主库的 binlog 文件拷贝过来离线解析。
常见错误现象:在从库执行 SHOW BINARY LOGS 发现一堆 relay-bin.xxxxx,误以为能用它们闪回;结果 mysqlbinlog 解析后只有碎片化事件,拼不出完整事务,WHERE 条件缺失,反向 SQL 无法执行。
- 确认来源:先在主库执行
SHOW MASTER STATUS;,拿到当前File和Position - 文件传输:用
scp或rsync把对应binlog文件(如/var/lib/mysql/mysql-bin.000042)拉到本地或恢复机 - 别碰从库
relay-log:它只用于复制重放,不是闪回依据
闪回前必须验证主库 binlog 三项配置是否齐全
缺一不可:log_bin=ON、binlog_format=ROW、binlog_row_image=full。这三项必须在误操作发生前就已启用,改完再重启 MySQL 对已写入的日志无效。
逐项检查命令:
-
SHOW VARIABLES LIKE 'log_bin';—— 必须返回ON,否则无日志可查 -
SHOW VARIABLES LIKE 'binlog_format';—— 必须是ROW,STATEMENT或MIXED格式下,DELETE或无WHERE的UPDATE只会记成DELETE FROM t,根本不知道删了哪几行 -
SHOW VARIABLES LIKE 'binlog_row_image';—— 必须是full,否则UPDATE只记录新值,DELETE不记录被删行快照,mysqlbinlog -v输出里只会看到@1=123,没有旧值字段
线上常有人只改了 binlog_format 却漏配 binlog_row_image,导致闪回时发现日志里“有操作但没数据”,白白浪费黄金恢复时间。
用 my2sql 精准生成回滚 SQL,避开 binlog2sql 在 8.0+ 的兼容坑
binlog2sql 在 MySQL 8.0+ 环境下大概率失败:认证插件不兼容、权限模型变更、对 mysql.user 表结构假设过时。当前最稳的选择是 my2sql,它纯离线解析,不连数据库,输出语句自带完整 WHERE 条件。
关键执行参数:
-
--work-type flashback:指定生成闪回语句 -
-B:生成反向语句(DELETE → INSERT,UPDATE → 反向 UPDATE) -
--start-pos和--stop-pos:必须卡在事务的BEGIN位置到COMMIT后一位,不能只选DELETE那一行——否则生成的INSERT缺少主键值,执行必报错 -
--d database_name -t table_name:限定范围,避免混入其他表操作
示例命令:
./my2sql_linux_amd64 -user root -password 'xxx' -host 127.0.0.1 -port 3306 \ -work-type flashback -B \ -d myapp -t orders \ --start-file mysql-bin.000042 --start-pos 123456 --stop-pos 789012 \ > rollback.sql
执行前必须绕开外键、主键、字符集三个硬性拦截点
直接把 rollback.sql 导入生产库,几乎必然中断:不是外键报错,就是主键冲突,或者字段乱码。
三步必须做:
- 禁用外键:
SET FOREIGN_KEY_CHECKS = 0;,执行完再设回1 - 检查主键冲突:误删后若有人插入了相同主键的新数据,
INSERT会失败。先运行SELECT * FROM orders WHERE order_id IN (1001,1002,...);确认目标主键是否已存在,存在则需先DELETE或重命名 - 统一字符集:确保
rollback.sql文件保存为utf8mb4编码,并导入时显式指定:mysql --default-character-set=utf8mb4 -u root -p myapp < rollback.sql
最容易被忽略的是 --start-pos 的起点——它必须是事务 BEGIN event 的位置,不是 DELETE event 的位置。这个位置要靠 mysqlbinlog --base64-output=decode-rows -v 手动翻找,或用 SHOW BINLOG EVENTS 查 Binlog Dump 后第一个 Query event 的 Pos。卡错一个字节,整条语句就废了。


















