mysql双主架构不提供增量备份能力,真正的增量备份必须依赖binlog+外部工具;需开启log-slave-updates、用row格式、禁用db过滤、独立日志路径,并通过gtid或位点精准切片归档。

MySQL双主架构本身不提供“增量备份”能力,它只是双向复制;真正的增量备份必须依赖 binlog + 外部工具或流程,且双主环境下极易因位点错乱、GTID冲突或回环导致备份不可用。
binlog 必须开,但配置方式和单主完全不同
双主环境的 log-bin 不是可选项,而是所有同步与备份的前提。但关键差异在于:
-
log-slave-updates=ON必须开启——否则从对方同步来的变更不会写入本地 binlog,后续增量备份就断在中间 -
binlog_format推荐ROW,避免STATEMENT在双写场景下因函数、临时表等产生不一致重放 - 不要依赖
binlog-do-db或replicate-do-db做过滤——它们不识别事件来源,无法阻止回环,纯属误导性配置 - 日志路径建议独立目录(如
/backup/binlogs/),避免与数据目录混放,方便备份脚本统一归档
mysqldump --master-data=2 在双主下直接失效
这是最常踩的坑:mysqldump --master-data=2 会从本机读取 SHOW MASTER STATUS,但在双主中,这位置大概率对应的是另一台机器的 binlog 文件名和 offset,恢复时必然报 Could not find first log file name in binary log index file。
- 正确做法:备份前执行
FLUSH TABLES WITH READ LOCK,再立刻SHOW MASTER STATUS记下File和Position(或Executed_Gtid_Set),dump 时不加--master-data,恢复后手动CHANGE REPLICATION SOURCE TO - 若已启用 GTID,备份时加
--set-gtid-purged=ON,但必须确认两端gtid_mode=ON且enforce_gtid_consistency=ON已在my.cnf中配置并重启生效 - 生产环境别用
mysqldump --all-databases直接打包——mysql、sys等系统库的 GTID 位点可能互相污染
增量备份只能靠 mysqlbinlog + 时间/位点切片
双主的 binlog 是交叉写入的(A 的写入 → B 的 binlog → A 的 relay log → A 的 binlog),所以不能简单按文件顺序归档。必须结合 GTID 或显式位点控制范围:
- 用
mysqlbinlog --skip-gtids --include-gtids='xxx-yyy:1-100'提取指定 GTID 区间,比靠start-position更可靠 - 若未开 GTID,备份脚本需记录每次全备后的
MASTER_LOG_FILE和MASTER_LOG_POS,后续增量只提取该位置之后、且来自本机 origin 的日志(可通过mysqlbinlog --base64-output=DECODE-ROWS -v观察server id字段) - 每天定时清理过期 binlog(
expire_logs_days=7),但清理前必须确保对应增量已归档,否则永久丢失
验证备份是否真能恢复,不能只看线程状态
双主环境里 SHOW REPLICA STATUS\G 显示 Seconds_Behind_Master: 0 完全不代表数据一致——可能两边都执行了冲突 UPDATE 却没报错,也可能自增 ID 已撞车但 SQL 线程仍在跑。
- 校验必须落到行级:
pt-table-checksum是唯一靠谱选择,它绕过复制协议,直接比对表内容哈希 - 定期在从库执行
SELECT COUNT(*)+MIN(id), MAX(id),检查自增 ID 是否符合预期分布(如 A 应只含奇数、B 只含偶数) - 用
MASTER_POS_WAIT()验证特定事务是否真正同步到对端,而不是靠Seconds_Behind_Master这个模糊指标
双主架构下所谓“备份”,本质是把复制链路本身当成备份通道来用,风险极高。最容易被忽略的一点是:你备份下来的 binlog,很可能包含大量重复、回环、甚至被跳过的事务——它不是干净的增量流,而是一段需要人工厘清来源和因果的数据杂音。











