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

不能直接 SET GLOBAL gtid_mode = ON,否则必然报错或导致从库 SQL_THREAD 启动失败——这是线上开启 GTID 最常踩的坑。
为什么 SET GLOBAL gtid_mode = ON 会报 ERROR 3098?
MySQL 5.7 强制要求:启用 gtid_mode = ON 前,集群中必须不存在任何匿名事务(即 gtid_next = AUTOMATIC 但未分配 GTID 的旧事务)。存量主从若长期运行在传统复制模式下,binlog 全是 0-0- 开头的事务 ID,此时直接设为 ON,就会触发 ERROR 3098 (HY000)。
- 执行
SELECT @@global.gtid_owned;返回非空,说明还有活跃匿名事务未落地 -
SHOW STATUS LIKE 'ONGOING_ANONYMOUS_TRANSACTION_COUNT';必须返回0才能进入下一步 - 该检查必须在所有主从节点上执行,且需等待至少 1–2 分钟确认无延迟或重试
必须分五步渐进切换,且每步全集群同步执行
GTID 模式不支持跳跃设置,顺序不可颠倒,每一步都必须在所有节点(主+从)上执行完毕并验证状态一致后,再推进下一步:
-
SET GLOBAL enforce_gtid_consistency = WARN;→ 观察错误日志 1–2 天高负载时段,确认无GTID consistency violated类警告 -
SET GLOBAL enforce_gtid_consistency = ON;→ 此时不兼容语句(如CREATE TABLE ... SELECT、含RAND()的事务)将直接报错,业务需配合改写 -
SET GLOBAL gtid_mode = OFF_PERMISSIVE;→ 主库不再生成 GTID,但从库仍可接收匿名和 GTID 事务 -
SET GLOBAL gtid_mode = ON_PERMISSIVE;→ 主库开始生成 GTID,但从库仍兼容两种事务;必须等ONGOING_ANONYMOUS_TRANSACTION_COUNT = 0后才能继续 -
SET GLOBAL gtid_mode = ON;→ 彻底禁用匿名事务;执行后立即在所有节点运行SELECT @@global.gtid_mode, @@global.enforce_gtid_consistency确认值均为ON
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' - 导入前,从库必须已执行
RESET SLAVE ALL(注意:RESET SLAVE不清空gtid_purged,会冲突) - 导入前确保从库从未执行过任何事务,否则
gtid_executed与 dump 中的GTID_PURGED冲突,START SLAVE直接报ERROR 1872
主从配置中 log_slave_updates=ON 是 GTID 复制的硬性前提
不开启 log_slave_updates,从库重放的事务不会写入自己的 binlog,导致 GTID 集合无法对齐,START SLAVE 会报 ERROR 3021 或 ERROR 1777。
- 主库和从库的
my.cnf都要设log_slave_updates = ON,不是“只主库开”就够了 - 从库建议显式配置
relay_log = relay-bin,避免默认命名导致RESET SLAVE ALL清理不干净 - 升级 GTID 前若从库原未开启该参数,需重启 mysqld 生效(
gtid_mode切换本身不可热生效)
最容易被忽略的是:五步切换中任意一步在某个从库上漏执行,或执行后没等足够时间观察 SHOW SLAVE STATUS\G,都会导致后续步骤失败,且问题现象往往滞后——比如 gtid_mode = ON 成功了,但几天后某次主从切换时才发现 Executed_Gtid_Set 对不上。


















