必须五步渐进切换gtid模式:先设enforce_gtid_consistency=warn并检查不兼容语句,再设on、off_permissive、on_permissive(确认ongoing_anonymous_transaction_count为0),最后设on;每步需全集群同步执行并验证状态。

为什么不能直接 SET GLOBAL gtid_mode = ON
MySQL 5.7 强制要求:启用 gtid_mode = ON 前,集群中必须不存在任何匿名事务(即 0-0- 开头的事务 ID)。存量主从若长期运行在传统复制模式下,binlog 全是匿名事务,此时直接执行 SET GLOBAL gtid_mode = ON 会报错,或导致从库 SQL_THREAD 启动失败、复制中断。
真正可行的路径是五步渐进切换,且每一步都必须在所有主从节点上**严格同步执行**:
-
SET GLOBAL enforce_gtid_consistency = WARN→ 观察错误日志是否有不兼容语句(如CREATE TABLE ... SELECT、含RAND()的 INSERT) -
SET GLOBAL enforce_gtid_consistency = ON→ 阻断新不兼容语句写入 -
SET GLOBAL gtid_mode = OFF_PERMISSIVE→ 允许执行带 GTID 的事务,但自身不生成 GTID -
SET GLOBAL gtid_mode = ON_PERMISSIVE→ 开始生成 GTID,但仍兼容旧匿名事务;执行后需确认SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT'返回0 -
SET GLOBAL gtid_mode = ON→ 彻底禁用匿名事务
每步执行后,必须在所有节点运行 SELECT @@global.gtid_mode, @@global.enforce_gtid_consistency 确认值一致,并等待至少 1–2 分钟观察 SHOW SLAVE STATUS\G 无延迟或错误。
mysqldump 初始化从库时 --set-gtid-purged=ON 是硬性要求
用传统方式 mysqldump --master-data=2 导出再导入,在 GTID 模式下必然失败,典型报错:Could not execute Write_rows event 或更隐蔽的 GTID_PURGED mismatch。
正确做法只有一种:
- 导出必须加
--set-gtid-purged=ON(MySQL 5.6.9+ 支持),它会在 dump 文件开头插入关键语句,包括SET @@GLOBAL.GTID_PURGED='xxx-xxx-xxx' - 导入前,从库必须满足:
gtid_mode=ON已生效、已执行RESET SLAVE ALL(RESET SLAVE不清空gtid_purged,会冲突)、且从未执行过任何事务(否则gtid_executed与 dump 中的GTID_PURGED不兼容) - 绝对不要用
--set-gtid-purged=OFF初始化 GTID 从库——这会让从库认为“自己没执行过任何 GTID 事务”,后续CHANGE MASTER TO MASTER_AUTO_POSITION=1必然失败
CHANGE MASTER TO 必须显式指定 MASTER_AUTO_POSITION=1
启用 GTID 后,CHANGE MASTER TO 不能再依赖 MASTER_LOG_FILE 和 MASTER_LOG_POS。必须显式指定 MASTER_AUTO_POSITION=1,否则会报错:ERROR 1777 (HY000): CHANGE MASTER TO requires MASTER_AUTO_POSITION = 1 when gtid_mode = ON。
实操要点:
- 从库执行:
STOP SLAVE; CHANGE MASTER TO MASTER_AUTO_POSITION = 1; START SLAVE; - 主库无需额外配置,只要自身
gtid_mode=ON且事务已落 binlog 即可响应请求 - 从库
gtid_executed不能包含与主库冲突的 GTID(例如导入 dump 时用了--set-gtid-purged=OFF,或残留了旧复制状态) - 检查从库当前 GTID 状态:
SELECT @@global.gtid_executed, @@global.gtid_purged;,对比主库SHOW MASTER STATUS;中的Executed_Gtid_Set
配置文件里 gtid_mode 和 enforce_gtid_consistency 必须写对位置
仅用 SET GLOBAL 设置不持久,MySQL 重启后回退。必须写入配置文件,且有明确限制:
- 参数必须写在
[mysqld]段内;写在[client]段或空白行完全不生效 -
gtid_mode = on或gtid_mode = ON合法;gtid_mode = 1或gtid_mode = true会被 mysqld 启动时静默忽略 -
enforce_gtid_consistency = ON是硬性前提,不是可选项——漏配会导致START SLAVE失败,日志里常出现误导性提示如[Warning] Neither --relay-log nor --relay-log-index were used - 主从两端的
gtid_mode和enforce_gtid_consistency必须严格一致,否则START SLAVE一定失败
最容易被忽略的是从库残留状态:如果之前用传统位置启动过复制,即使改了配置,gtid_executed 和 gtid_purged 可能仍为空或与主库不匹配,导致 START SLAVE 卡在 relay log 初始化阶段,报错类似 Slave failed to initialize relay log info structure。











