必须确认binlog_format为ROW、文件未压缩、GTID设置正确且事务边界对齐,否则解析失败或恢复出错;导出需加--skip-gtids或--include-gtids,测试须校验INNODB_TRX和CHECKSUM TABLE。

用 mysqlbinlog 解析 binlog 前必须确认格式和位置
MySQL 增量恢复依赖 binlog,但不是所有 binlog 都能直接解析回放。常见错误是拿到一个 mysql-bin.000001 就直接丢给 mysqlbinlog,结果报错 Unknown binlog format 或解析出一堆乱码。
根本原因是 binlog_format 必须为 ROW(推荐)或 STATEMENT,而 MIXED 在某些操作下会退化,导致解析后 SQL 不可逆;另外,binlog 文件可能被压缩(如 mysql-bin.000001.gz),mysqlbinlog 默认不支持解压,得先 gunzip。
- 检查当前格式:
SHOW VARIABLES LIKE 'binlog_format';,生产环境务必设为ROW - 确认 binlog 开启且未过期:
SHOW BINARY LOGS;,注意EXPIRE_LOGS_DAYS设置 - 解析前先验证文件可读:
mysqlbinlog --base64-output=decode-rows -v mysql-bin.000001 | head -20,加-v和--base64-output=decode-rows才能看到真实变更行
从指定 position 或 GTID 恢复时别跳过 SET @@SESSION.GTID_NEXT
用 mysqlbinlog 导出 SQL 后直接导入,常出现主键冲突或“Duplicate entry”错误——不是数据重复,而是 GTID 模式下 MySQL 拒绝执行已记录过的事务。
典型场景:你从备份点 A 恢复全量,再想从 binlog 中截取 A→B 的增量段回放。如果导出的 SQL 里没保留原始 SET @@SESSION.GTID_NEXT,MySQL 会自动生成新 GTID,导致后续事务无法按序应用,甚至中断复制链。
- 导出时必须加
--skip-gtids(用于测试恢复)或--include-gtids='...'(用于精准重放),不能只靠--start-position - 若用 GTID 恢复,先查出起始点:
SELECT * FROM mysql.gtid_executed WHERE source_uuid = 'xxx' ORDER BY interval_start LIMIT 1; - 导入前手动在 SQL 文件头加
SET SESSION sql_log_bin = 0;,避免二次写入 binlog
测试恢复必须在隔离环境做,且要校验 information_schema.INNODB_TRX
很多人把 dump + binlog 回放脚本扔进测试库就认为“流程走通了”,结果上线后发现某张表少了几百条更新——问题往往出在事务边界没对齐,或者回放中途被 kill 导致部分事务残留锁。
增量恢复不是“SQL 跑完就完事”,它本质是重放事务流。测试时若不观察事务状态,很容易误判成功。
- 恢复前清空测试库的
mysql.gtid_executed表(仅限测试环境),避免 GTID 冲突 - 恢复过程中实时查:
SELECT trx_id, trx_state, trx_started, trx_query FROM information_schema.INNODB_TRX;,确保没有长事务卡住 - 恢复后对比源库与测试库的
CHECKSUM TABLE t1;,比SELECT COUNT(*)更可靠,尤其对大表
mysqlpump 和 mysqldump 对增量恢复的影响差异
全量备份工具选错,会让后续增量恢复变成灾难。比如用 mysqldump --single-transaction 备份时,若遇到 DDL(如 ALTER TABLE),事务快照会失效,导致 binlog 位点和 dump 文件逻辑不一致。
mysqlpump 默认按表并行导出,且对 DDL 更友好,但它的 --set-gtid-purged 行为和 mysqldump 不同,容易在恢复时漏掉 GTID 设置。
- 全量备份必须带
--master-data=2(mysqldump)或--set-gtid-purged=ON(mysqlpump),否则找不到 binlog 起始位置 - 若备份中含
CREATE DATABASE,恢复时记得加--force,否则库已存在会中断 - 不要混合使用两种工具做同一套恢复流程,GTID 解析逻辑不同,
mysqlpump导出的SET @@GLOBAL.GTID_PURGED是合并后的区间,mysqldump是单点
真正难的不是跑通命令,而是确认每一步的事务边界、GTID 连续性和表级一致性。一次没校验 checksum,就可能让故障演练变成真实事故预演。


















