必须显式指定--set-gtid-purged=on以确保备份含gtid_purged语句,避免恢复时因gtid不连续报错;若源库刚执行reset master则改用off,并确保目标实例同步清空gtid_executed。

mysqldump 备份时必须加 --set-gtid-purged=ON
不加这个参数,备份出来的 SQL 文件里不会包含 SET @@GLOBAL.GTID_PURGED 语句,恢复到新实例后,从库会因 GTID 不连续而拒绝执行事务。MySQL 默认行为是 --set-gtid-purged=auto,但 auto 在某些场景(比如只备份部分库、或源库有未清除的 binlog)会退化为 OFF,导致静默失败。
实操建议:
- 始终显式指定
--set-gtid-purged=ON,哪怕看起来“多此一举” - 如果备份前刚执行过
RESET MASTER,--set-gtid-purged=ON会报错(因为GTID_PURGED为空),此时改用--set-gtid-purged=OFF,但需确保目标实例也执行过RESET MASTER或已清空GTID_EXECUTED - 避免在备份命令中混用
--single-transaction和--all-databases:前者对非事务表无效,后者可能包含mysql系统库,而系统库里的表(如gtid_executed)不支持事务一致性快照
恢复前必须检查目标实例的 GTID_MODE 和 GTID_EXECUTED
直接 source 备份 SQL 文件大概率失败——不是语法错,而是 MySQL 拒绝执行,报错类似:ERROR 1840 (HY000): @@GLOBAL.GTID_PURGED can only be set when @@GLOBAL.GTID_EXECUTED is empty。这是因为目标实例已有 GTID 历史,但你试图用 SET @@GLOBAL.GTID_PURGED 覆盖它。
实操建议:
- 恢复前先查:
SELECT @@GLOBAL.GTID_MODE, @@GLOBAL.GTID_EXECUTED; - 如果
GTID_EXECUTED非空,且你不是做主从搭建而是全新导入,必须先执行RESET MASTER(注意:这会清空所有 binlog) - 若不能清空 binlog(比如实例正在被其他从库复制),就得手动合并 GTID:用
SELECT GTID_SUBTRACT(@@GLOBAL.GTID_EXECUTED, '已知备份中的 GTID_PURGED 值')看是否有冲突;有则说明备份不可直接用
GTID_PURGED 不等于备份时刻的全部已执行 GTID
备份文件开头的 SET @@GLOBAL.GTID_PURGED='...' 实际是 GTID_EXECUTED - GTID_OWNED 的快照,即排除了正在执行的事务。但更关键的是:它只反映备份开始时的状态,不包含备份过程中新产生的事务(mysqldump 自身也会生成 GTID)。所以这个值本质是“安全下界”,不是精确快照。
实操建议:
- 不要拿备份文件里的
GTID_PURGED值去反推备份耗时或校验数据一致性 - 如果需要强一致性点位,应在备份前先执行
FLUSH TABLES WITH READ LOCK; SELECT @@GLOBAL.GTID_EXECUTED;,再立即mysqldump --set-gtid-purged=OFF,最后UNLOCK TABLES - 生产环境做逻辑备份时,优先考虑
mysqlpump或mydumper,它们对 GTID 的处理更透明,错误提示也更明确
跳过 GTID 冲突的临时方案很危险
有人遇到 ERROR 1062 (23000): Duplicate entry for key 'PRIMARY' 或 ERROR 3546 (HY000): Cannot add or update a child row 就想加 SET SESSION GTID_NEXT='AUTOMATIC' 或 SET GLOBAL sql_slave_skip_counter=1,这是把 GTID 当成普通主从跳错来处理,完全错误。
实操建议:
-
sql_slave_skip_counter在 GTID 模式下已被废弃,设了也没用 -
GTID_NEXT手动设值极易导致 GTID 集合错乱,后续无法再正确同步 - 真正该做的是:确认备份是否完整、目标实例是否干净、
GTID_PURGED是否被意外覆盖过——大部分“冲突”其实源于恢复前没RESET MASTER或误删了mysql.gtid_executed表
GTID 备份最麻烦的从来不是命令怎么写,而是你得同时盯住三个地方:备份时源库的 GTID_EXECUTED、备份文件里写的 GTID_PURGED、恢复前目标库的 GTID_EXECUTED。少看一个,后面就卡在 START SLAVE 上动不了。










