MySQL 5.7 不支持基于数据页变更的物理增量备份,只能通过 mysqldump 全备 + mysqlbinlog 截取 binlog 实现事务级逻辑增量恢复;mysqldump 是纯逻辑工具,无 LSN 感知能力,不支持真正增量;binlog 是唯一可行增量来源,但必须与全备配合并确保连续性、可验证性。

MySQL 5.7 本身不支持“基于数据页变更”的增量备份,但可以用 mysqldump 全备 + mysqlbinlog 截取 binlog 实现逻辑层面的增量恢复——这不是 LSN 级物理增量,而是时间点可追溯的事务级增量。
为什么不能用 mysqldump 做真正的增量备份
mysqldump 是纯逻辑工具,它不读取 InnoDB 数据页头部的 LSN,也不感知物理页是否被修改。即使加了 --single-transaction,也只是靠 MVCC 快照保证一致性,输出仍是完整 SQL。它没有 --incremental 参数,也没有任何机制跳过未变更的表或行。
- 每次执行都是全库/全表导出,备份体积与数据量正相关,和变更量无关
- 无法识别“自上次 dump 后哪些行被 INSERT/UPDATE/DELETE”
- 若强行用 diff 比较两个 SQL 文件来“模拟增量”,会漏掉 DDL、权限变更、主从位点偏移等关键信息
binlog 是唯一可行的增量来源,但必须配合全备使用
MySQL 5.7 的二进制日志(binlog)记录的是事务提交后的逻辑变更事件(取决于 binlog_format:STATEMENT / ROW / MIXED),粒度是语句或行,不是页。它能支撑“从某次全备之后恢复到任意时间点”,但不是自动识别“哪些数据变了”的智能增量。
- 必须提前开启
log_bin,并配置server-id(即使单机) - 全备后立即执行
FLUSH LOGS,让后续 binlog 从新文件开始,便于定位起点 - 增量备份本质是复制新生成的 binlog 文件(如
mysql-bin.000012),或用mysqlbinlog --start-position=xxx截取片段 - 恢复时顺序固定:
mysqldump全备 →mysqlbinlog回放(按时间/position 顺序)
实际脚本中容易踩的坑
很多线上脚本直接 cp 最新的 binlog 文件,看似简单,但极易出错:
- 没校验 binlog 是否已 rotate:用
SHOW BINARY LOGS查当前活跃文件,避免复制正在写的文件导致损坏 - 没处理
FLUSH LOGS和备份时间差:全备脚本末尾必须FLUSH LOGS,然后立刻记录新文件名(如mysql-bin.000013),否则增量起点不明确 - 忽略 GTID 模式:若启用
gtid_mode=ON,就不能用 position,必须用--include-gtids或解析gtid_purged,否则回放会跳过或重复 - 没压缩或没校验:binlog 是二进制文件,直接 rsync 易出错;建议用
mysqlbinlog --base64-output=DECODE-ROWS -v做人工抽检
恢复失败最常见的原因
不是命令写错,而是链路断裂:
- 全备 SQL 中没包含
SET @@GLOBAL.GTID_PURGED='...'(GTID 模式下必须) - binlog 文件缺失一个:比如周一全备,周二、三增量都正常,周四的 binlog 文件因磁盘满没写完,整个链就断了
- 恢复时 MySQL server_id 与原库冲突,导致 binlog 回放被忽略(尤其在测试环境复现时)
- 全备未加
--master-data=2,导致找不到起始 position,只能靠SHOW MASTER STATUS手动记,极易出错
真正可靠的增量链,依赖的是 binlog 的连续性与可验证性,而不是“每天 cp 一个文件”这种表面操作。一旦中间任一环节不可信,整条恢复路径就失去意义。











