mysql闪回需满足binlog开启、格式为row、行镜像为full三个条件;定位误删需用mysqlbinlog按时间切片获取事务起止position;用my2sql解析生成带事务包装的insert语句,执行前关sql_log_bin并校验数据。

能闪回,但必须满足三个硬性条件:binlog 开启、格式为 ROW、行镜像为 FULL;缺一不可,否则 pt-flashback 或 my2sql 会直接报错或生成空/错误 SQL。
确认 binlog 配置是否支持闪回
闪回不是“有 binlog 就能用”,而是依赖日志里有没有被删行的完整旧值(before image)。STATEMENT 格式只记 DELETE FROM t WHERE id=1,根本不知道那一行原来是什么;MINIMAL 行镜像可能只记主键,其他字段全丢。
-
SHOW VARIABLES LIKE 'log_bin'必须返回ON -
SHOW VARIABLES LIKE 'binlog_format'必须是ROW -
SHOW VARIABLES LIKE 'binlog_row_image'必须是FULL(MINIMAL或NOBLOB会导致字段缺失) - 误删后没执行过
FLUSH LOGS或重启 mysqld,否则关键 binlog 可能已轮转丢失
定位误删事件的起止 position
别靠肉眼翻整个 binlog 文件——大日志解析极慢,还容易漏掉事务边界。要用 mysqlbinlog 加时间或关键词精准切片:
- 先用时间粗筛:
mysqlbinlog --base64-output=DECODE-ROWS -v --start-datetime="2026-10-15 12:00:00" --stop-datetime="2026-10-15 13:00:00" /var/lib/mysql/mysql-bin.000012 | grep -A 5 -B 5 "DELETE FROM `mydb`.`users"` - 找到目标事件后,记下它的
# at 123456(起始位置)和紧随其后的下一个# at(比如# at 123987),这就是该 DELETE 事务的范围 - 注意:一个 DELETE 语句可能跨多个 event(BEGIN、TABLE_MAP、WRITE_ROWS/DELETE_ROWS、XID),必须取整个事务段,不能只截单个 DELETE_ROWS
用 my2sql 生成可执行的 INSERT 回滚语句
my2sql 是目前最稳的选择,支持 MySQL 8.0、离线解析、不连数据库,且输出 SQL 带注释和事务包装,人工审核成本低。它比 pt-flashback 更明确区分 DML 类型,不会把 UPDATE 误当 DELETE 处理。
- 安装后直接解析:
my2sql -user root -password 'xxx' -host 127.0.0.1 -port 3306 -work-type flashback -start-file mysql-bin.000012 -start-pos 123456 -stop-pos 123987 -databases mydb -tables users - 输出默认是
flashback.sql,内容类似:START TRANSACTION; INSERT INTO `mydb`.`users` (`id`, `name`, `email`) VALUES (1001, 'Alice', 'a@b.com'); INSERT INTO `mydb`.`users` (`id`, `name`, `email`) VALUES (1002, 'Bob', 'b@c.com'); COMMIT;
- 务必检查生成的 SQL:字段顺序是否与当前表结构一致?是否有新增列导致
INSERT字段数不匹配?外键约束是否仍有效?
执行前必须关掉 binlog 写入并验证环境
直接在原库上跑回滚 SQL,等于把恢复操作又写进 binlog,万一出错就更难收场。而且如果表上有触发器或唯一索引冲突,INSERT 会直接失败。
- 先在目标库执行:
SET SESSION SQL_LOG_BIN = 0;(避免恢复过程再记 binlog) - 用
SELECT COUNT(*)和抽样SELECT * FROM users WHERE id IN (1001,1002)确认这些 ID 当前确实不存在 - 如果表有自增主键,且误删后已有新数据插入,回滚的
INSERT可能撞上重复主键,得加ON DUPLICATE KEY UPDATE或先DELETE冲突行 - 最后才执行
source flashback.sql,别跳过事务包装
最容易被忽略的一点:闪回只能还原“被删的行”,不能还原“删完之后又插入的新行”。如果你在误删后又手动补了几条数据,它们会被你刚执行的 INSERT 覆盖——所以恢复前一定要确认业务层没有二次写入。











