不能直接将gtid_mode设为ON,因为MySQL强制要求切换前集群中不存在任何匿名事务;存量传统复制的binlog全是匿名事务,直接设ON会报错或导致从库SQL线程启动失败,必须经WARN→ON→OFF_PERMISSIVE→ON_PERMISSIVE→ON五步渐进切换,并确保所有节点同步执行、匿名事务清零后方可完成。

MySQL 5.7 不能直接在主从已运行的集群上“开启 GTID”就完事——必须按五步渐进切换,且所有节点严格同步执行,否则复制立即中断或数据不一致。
gtid_mode 为什么不能直接设为 ON
MySQL 强制要求:GTID 模式启用前,必须确认集群中**不存在任何匿名事务(Anonymous GTID)**。而存量主从如果长期运行在传统模式下,binlog 里全是 0-0- 开头的事务标识,SET GLOBAL gtid_mode = ON 会直接报错或导致从库 SQL 线程拒绝启动。
真正安全的路径是分阶段过渡:
-
SET GLOBAL enforce_gtid_consistency = WARN→ 观察错误日志里是否有不兼容语句(如CREATE TABLE ... SELECT、RAND()) -
SET GLOBAL enforce_gtid_consistency = ON→ 阻断新不兼容语句写入 -
SET GLOBAL gtid_mode = OFF_PERMISSIVE→ 允许混用匿名/带 GTID 事务,但只读取不生成新 GTID -
SET GLOBAL gtid_mode = ON_PERMISSIVE→ 开始生成 GTID,但仍兼容旧事务 -
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... BINLOG_FORMAT = STATEMENT 或更隐蔽的 GTID_PURGED mismatch。
正确做法只有这一种:
- 导出必须加
--set-gtid-purged=ON(MySQL 5.6.9+ 支持),它会在 dump 文件开头插入两行关键语句:SET @MYSQLDUMP_TEMP_LOG_BIN = @@SESSION.SQL_LOG_BIN;SET @@SESSION.SQL_LOG_BIN= 0;SET @@GLOBAL.GTID_PURGED='xxx-xxx-xxx'; - 导入前确保从库
gtid_mode=ON且未执行过任何事务(否则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。这些字段在 GTID 模式下被忽略,强行填写反而可能触发非预期行为(比如跳过部分事务)。
标准命令是:
CHANGE MASTER TO MASTER_HOST='192.168.2.171', MASTER_PORT=3306, MASTER_USER='repluser', MASTER_PASSWORD='Abcd@1234', MASTER_AUTO_POSITION=1;
注意点:
-
MASTER_AUTO_POSITION=1表示启用 GTID 自动定位,从库会基于gtid_executed和主库的Executed_Gtid_Set自动计算需要拉取的事务范围 - 执行前务必先
STOP SLAVE,否则会报错ERROR 3021 (HY000): The slave is not configured or failed to initialize - 成功后
SHOW SLAVE STATUS\G中Auto_Position: 1必须为 1,且Retrieved_Gtid_Set和Executed_Gtid_Set应持续增长
最容易被忽略的配置项:log_slave_updates 和 server-uuid
这两个不是可选项,而是 GTID 复制能链式传递的前提:
-
log_slave_updates=ON必须在**所有从库**(包括级联从库)的配置文件中显式设置并重启生效;否则该从库无法将重放的事务写入自己的 binlog,下游从库就收不到 GTID,复制链断裂 -
server-uuid必须全局唯一,由 MySQL 启动时自动生成(存于auto.cnf)。若克隆虚拟机或复制数据目录,必须删除原auto.cnf让 MySQL 重生成,否则多个实例 UUID 相同会导致 GTID 冲突、事务被跳过甚至数据覆盖 - 另外两个常漏配但关键的项:
master-info-repository=TABLE和relay-log-info-repository=TABLE,它们让复制元数据持久化到表而非文件,避免 mysqld 意外崩溃后丢失位置信息
GTID 的可靠性不来自“自动”,而来自对每个环节的显式约束——少配一项,就可能在某个低峰夜凌晨三点让你收到告警。











