必须在所有节点同时启用gtid_mode=ON且enforce_gtid_consistency=ON,否则复制无法启动;需MySQL 5.7+、log_bin=ON、binlog_format=ROW、server_id全局唯一,并正确设置--set-gtid-purged与RESET SLAVE ALL顺序。

必须在所有节点同时启用 gtid_mode=ON 且 enforce_gtid_consistency=ON,否则复制无法启动,不是“配了就能用”。
确认 MySQL 版本与基础参数是否达标
GTID 从 MySQL 5.6 引入,但生产环境强烈建议使用 5.7 或 8.0——5.6 存在已知的 GTID 初始化异常和 purged 处理缺陷。运行以下命令验证关键状态:
SELECT @@version, @@gtid_mode, @@enforce_gtid_consistency, @@log_bin, @@binlog_format, @@server_id;
必须全部满足:
-
@@gtid_mode = ON(不能是ON_PERMISSIVE) @@enforce_gtid_consistency = ON-
@@log_bin = ON且@@binlog_format = 'ROW' -
@@server_id在集群中全局唯一(主从不能相同)
任一不满足,修改 my.cnf 后需重启 mysqld;gtid_mode 切换不可动态生效。
主库与从库的配置差异点
主库和从库的 my.cnf 都要加 GTID 相关项,但有两处易错细节:
- 主库必须设
log_slave_updates = ON(级联复制或故障后旧主重入为从时必需) - 从库也建议设
log_slave_updates = ON,否则它无法作为新主库被其他从库接入 - 从库需显式启用中继日志:
relay_log = relay-bin(不设可能生成默认命名的中继日志,导致RESET SLAVE ALL清理不干净)
错误示例:只在主库开 log_slave_updates,从库没开 → 故障切换后,其他从库连不上这个“新主”,因为它的 binlog 里没有 relay 过来的事务。
备份恢复时 --set-gtid-purged 必须设对
用 mysqldump 搭建从库或恢复数据时,--set-gtid-purged 参数决定新实例能否加入 GTID 复制链:
-
--set-gtid-purged=ON(默认):dump 文件头部会写入SET @@GLOBAL.gtid_purged = 'xxx:1-100';,导入后新实例自带 GTID 上下文 -
--set-gtid-purged=OFF:导入后@@global.gtid_executed为空,START SLAVE会报ERROR 1872 (HY000),提示 GTID set 不匹配 - 若误用了
OFF,只能手动执行SET GLOBAL gtid_purged = 'xxx:1-100';(值来自原主库的SELECT @@global.gtid_executed;)
物理备份(如 XtraBackup)恢复后同样要手动设置 gtid_purged,否则复制线程拒绝启动。
故障切换时 RESET SLAVE ALL 和 gtid_purged 设置顺序不能反
从库提升为主库的核心动作不是“停复制”,而是让它的 GTID 状态可被下游识别。常见错误是漏掉 ALL 或顺序颠倒:
- 先执行
STOP SLAVE; - 再执行
RESET SLAVE ALL;(注意必须带ALL,否则gtid_purged不清空,后续SET GLOBAL gtid_purged会失败) - 然后查原主库的
SELECT @@global.gtid_executed;,把结果赋给新主:SET GLOBAL gtid_purged = 'e1e2f3a4-...:1-100';
如果跳过 RESET SLAVE ALL 直接 SET GLOBAL gtid_purged,MySQL 会报 ERROR 1840 (HY000):“GTID_PURGED can only be set when GTID_EXECUTED is empty”。
GTID 的可靠性不来自自动选主,而来自“每个事务只执行一次”的硬约束;真正容易出问题的,是备份导入时的 --set-gtid-purged 和切换时 RESET SLAVE ALL 的遗漏——这两步一旦错,整个复制链就断在 GTID 校验上,不会报具体哪条事务缺失,只显示同步失败。


















