必须执行 reset slave all,因其清空 relay log、master info 表及复制元数据(含 gtid_purged),仅 reset slave 不足;gtid_purged 必须手动设为导出时刻主库的 executed_gtid_set 精确值,且导入后立即设置、禁止任何 dml/ddl。

直接给结论:用 mysqldump --set-gtid-purged=ON 导出 + 从库先 RESET SLAVE ALL + 导入后立即 SET GLOBAL gtid_purged = 'xxx',三步缺一不可。跳过任一环节,START SLAVE 必报 ERROR 1872。
为什么不能跳过 RESET SLAVE ALL?
从库如果之前运行过复制,relay_log 和 master_info_repository 里存着旧的 GTID 位点和 binlog 文件名/位置信息。这些残留会和新导入数据的 GTID 上下文冲突,导致 MASTER_AUTO_POSITION = 1 启动时无法对齐事务链。
-
RESET SLAVE ALL清空 relay log、master info 表、gtid_executed和gtid_purged(注意:不是清空gtid_executed,而是重置复制元数据) - 只用
RESET SLAVE不够——它不清理gtid_purged,也不清空基于表存储的 master info(当master_info_repository = 'TABLE'时) - 执行前确认从库已停复制:
STOP SLAVE;否则命令可能被忽略或部分生效
gtid_purged 值从哪来?必须手动设吗?
必须设,且必须准确。dump 文件头部的 SET @@GLOBAL.gtid_purged = '...' 是主库导出时刻的 gtid_executed,但它不等于你导入后需要设的值——因为 dump 过程中主库可能又提交了新事务。
- 最稳妥来源是主库执行
SHOW MASTER STATUS,取Executed_Gtid_Set字段完整值(不是Retrieved_Gtid_Set) - 若 dump 文件已生成且没丢,可直接 grep:
grep "gtid_purged" Fulldb.sql | head -1 - 严禁在从库导入后执行
RESET MASTER再设 ——这会清空gtid_executed,让gtid_purged失去计算基础,后续START SLAVE直接失败
CHANGE MASTER TO 时 MASTER_AUTO_POSITION = 1 的硬性前提
这个参数不是“开了就能用”,它依赖从库的 gtid_executed 和主库的 gtid_executed 有交集。而刚导入的数据默认 gtid_executed 为空,所以必须靠 gtid_purged 来补全历史上下文。
- 导入 SQL 后,从库的
gtid_executed仍为空(除非 dump 文件里含GTID_NEXT显式事务) - 此时
gtid_purged就成了唯一能告诉从库“我其实已经执行过哪些事务”的依据 -
MASTER_AUTO_POSITION = 1启动时,MySQL 会用从库的gtid_executed ∪ gtid_purged去和主库协商起始位置;缺了gtid_purged,就等于说“我什么都没执行过”,主库找不到匹配点
最容易被忽略的是:导入 dump 后、设 gtid_purged 前,千万别执行任何 DML 或 DDL。哪怕只是 CREATE DATABASE test,都会让 gtid_executed 变成非空但不连续的集合,破坏 GTID 链完整性,后续同步大概率卡在第一个事务。











