必须满足binlog_format=ROW且binlog_row_image=FULL;缺一不可,否则闪回工具生成的SQL会漏字段、错主键或无效,重启改配置已无意义,只能依赖备份。

闪回必须满足的两个硬性配置条件
不满足就别往下看了——binlog_format 必须是 ROW,binlog_row_image 必须是 FULL。缺一不可。
用这条 SQL 检查:
mysql> SHOW VARIABLES LIKE 'binlog_format';<br>mysql> SHOW VARIABLES LIKE 'binlog_row_image';
如果返回不是 ROW 和 FULL,立刻停手。闪回工具(包括 my2sql、MyFlash、binlog2sql)解析出来的 SQL 会漏字段、错主键,甚至生成无效语句。改配置要重启 MySQL,但此时已发生误操作,重启无意义,只能切备份。
-
STATEMENT或MIXED格式下,mysqlbinlog -B会直接报错或输出空内容 -
binlog_row_image=MINIMAL时,UPDATE 只记变更列,DELETE 不记旧值,闪回 INSERT 时缺字段,执行必失败 - 线上环境建议在初始化实例时就固化这两项,而不是出事后再查
选哪个工具:my2sql 是当前最稳妥的选择
MySQL 5.7 用 binlog2sql 还能凑合,但如果你用的是 8.0(2026 年主流版本),binlog2sql 已停止维护,解析 GTID_LOG_EVENT 或新权限字段会崩溃;MyFlash 虽快,但只支持单个 binlog 文件,遇到跨文件的长事务就断档。
my2sql(Go 语言)是目前唯一同时满足以下四点的工具:
- 原生支持 MySQL 8.0 的
ANONYMOUS_GTID_LOG_EVENT和新系统表结构 - 可离线解析多个 binlog 文件(如
mysql-bin.000012到mysql-bin.000015) - 自带
--dmltype和--table过滤,避免把无关表的 DML 也翻出来 - 输出含
@1/@2占位符的 SQL,和mysqlbinlog --base64-output=DECODE-ROWS输出一致,可直接比对校验
安装后验证是否可用:
$ ./my2sql -h<br>Usage: my2sql [OPTIONS]
没报段错误、没缺 libgo.so 就算过第一关。
定位误操作位置:别靠 guess,用时间 + pos 双锁定
误删/误更新后第一件事不是跑工具,而是锁表 + 记录现场:
mysql> LOCK TABLES your_table_name READ;<br>mysql> SHOW MASTER STATUS;
拿到当前 File 和 Position(比如 mysql-bin.000023,19872),再结合误操作大致时间(精确到分钟即可),用 my2sql 定界:
$ ./my2sql \<br> --start-file mysql-bin.000022 \<br> --start-pos 4 \<br> --stop-file mysql-bin.000023 \<br> --stop-pos 19872 \<br> --database your_db \<br> --table your_table \<br> --flashback > rollback.sql
关键点:
-
--start-pos 4是每个 binlog 文件的固定起始偏移,别写成 0 -
--flashback参数才生成逆向 SQL;不加就是原始操作 SQL - 如果误操作跨了多个 binlog,
--stop-file必须设为最后一个文件,不能只扫当前文件 - 生成的
rollback.sql里每条语句开头带-- timestamp: 2026-06-02 06:22:18,方便人工核对
执行前必须做的三件事
生成的 SQL 不是“拿来就能跑”。直接 mysql < rollback.sql 是线上事故高发动作。
- 先在测试库建同名表、导入相同数据,跑一遍
rollback.sql,看是否语法报错、主键冲突、字段数不匹配 - 检查 SQL 里有没有
INSERT INTO ... SELECT或子查询——这类语句在 flashback 模式下可能被错误还原,需手动改成 VALUES 形式 - 确认目标表没有触发器:
SHOW TRIGGERS LIKE 'your_table';,有则临时禁用,否则回滚时触发器二次写入会导致数据错乱
最后执行时,加 -f(force)参数跳过警告,但必须用 --default-character-set=utf8mb4 避免中文乱码插入失败。
真正难的从来不是工具调用,而是判断哪一段 binlog 属于“那个误操作”——日志里混着正常业务流量,删错一行和删错一万行,在 my2sql 输出里只差一个 @1 值。定位不准,回滚就是往火坑里跳。


















