能找回,前提是 binlog_format=row 且日志未轮转或删除;需先确认 log_bin=on、binlog_format=row、binlog_row_image=full,再用 mysqlbinlog 或 myflash 解析日志提取反向 insert 语句恢复。

能找回,前提是 binlog_format=ROW 且日志没被轮转或删掉。否则基本没戏。
确认 binlog 是否可用且格式正确
这是所有恢复操作的前提,跳过这步直接上手解析日志,大概率白忙活。
- 连上 MySQL 执行
SHOW VARIABLES LIKE 'log_bin';,返回ON才行 - 再查
SHOW VARIABLES LIKE 'binlog_format';,必须是ROW;STATEMENT模式下无法还原被删的行内容 - 检查
binlog_row_image,推荐值是FULL(默认),MINIMAL会导致部分字段缺失,影响 INSERT 回填 - 运行
SHOW MASTER STATUS;看当前写入位置,再用SHOW BINARY LOGS;列出所有文件,确认误删操作发生时的日志还在
用 mysqlbinlog 定位并提取 DELETE 对应的反向 INSERT
别指望人工从一堆 base64 里找数据——mysqlbinlog 默认输出的是不可执行的注释+事件结构,必须加参数才能看到原始行数据。
- 先用时间范围粗筛:
mysqlbinlog --base64-output=decode-rows -v --start-datetime="2026-07-01 14:20:00" --stop-datetime="2026-07-01 14:25:00" /var/lib/mysql/mysql-bin.000015 > /tmp/del_analysis.sql - 关键参数不能少:
--base64-output=decode-rows解码行事件,-v输出详细结构,否则你看不到DELETE_ROWS_EVENT里的values字段 - 在输出文件里搜索
### DELETE FROM和紧随其后的### INSERT INTO块(这是 ROW 模式下自动生成的反向语句),复制出来单独保存为restore.sql - 如果时间不准,改用 position 定位:
mysqlbinlog --base64-output=decode-rows -v --start-position=123456 --stop-position=123999 mysql-bin.000015 > /tmp/pos_restore.sql,position 来自SHOW BINLOG EVENTS或上一步分析结果
用 MyFlash 工具一键生成回滚 SQL(推荐给非 DBA)
手动解析容易漏字段、错表名,尤其多表 JOIN 或 JSON 字段时。MyFlash 是美团开源的成熟工具,专治这类问题,但依赖 ROW + FULL 模式。
- 编译安装后,执行:
./flashback --binlog_file_list="mysql-bin.000015" --out_binlog_name="rollback" - 它会自动扫描日志,识别
DeleteRowsEvent,生成带INSERT的rollback.binlog - 注意:生成的文件仍是二进制格式,需再用
mysqlbinlog转成 SQL:mysqlbinlog rollback.binlog > rollback.sql - 导入前务必在测试库验证:
mysql -D testdb ,确认数据对得上再上生产
执行恢复前必须做的三件事
很多人卡在最后一步——不是不会恢复,是恢复完发现主键冲突、唯一索引报错、或者覆盖了后续正常写入的数据。
- 把目标表设为只读或 rename 备份:
RENAME TABLE orders TO orders_bak_20260702;,避免恢复时写冲突 - 确认恢复的 SQL 不含
WHERE条件的UPDATE或全表DELETE——MyFlash 有时会把邻近事件也卷进来,得人工 grep 过滤 - 如果原表有自增主键,恢复后记得
ALTER TABLE orders AUTO_INCREMENT = [最大现有ID + 1];,否则下次插入可能报错
最易被忽略的一点:mysqlbinlog 解析出的 SQL 默认不带 USE database_name,跨库操作时会执行到错误库中。要么加 --database=your_db 参数限定,要么手动在 SQL 文件头补上 USE your_db;。











