GTID 是什么:不是“ID”,而是复制坐标系统
GTID 不是给事务随便打个标签的编号,它是 MySQL 主从复制中替代
binlog_file+
binlog_pos的全新定位机制。每个事务在提交时被赋予一个形如
3E11FA47-71CA-11E1-9E33-C80AA9429562:23的标识——前半段是主库的
server_uuid(写死在
auto.cnf里),后半段是该实例上第 23 个已提交事务的序列号。
关键在于:这个组合在整个复制拓扑中全局唯一,且从不重复。它让从库不再靠“我在 mysql-bin.000003 的第 12489 字节”这种脆弱位置来同步,而是靠“我已执行
a3558952-9176-11f0-b428-5254007ccb52:1-2,请把后面没执行过的都给我”来驱动复制。
开启 GTID 的硬性前提:三参数缺一不可
只配
gtid_mode=ON是无效的,MySQL 启动时会静默降级回传统模式。必须同时满足以下三项,否则
SHOW VARIABLES LIKE 'gtid_mode'显示为
OFF:
gtid_mode=ON:启用 GTID 生成功能
enforce_gtid_consistency=ON:强制事务合规(禁用
CREATE TABLE ... SELECT、
TEMPORARY TABLE、非事务引擎等)
log_slave_updates=ON:从库也必须写 binlog(否则无法向下游传递 GTID)
漏掉
log_slave_updates是最常被忽略的坑——尤其在级联复制场景下,中间从库不写 binlog,下游就收不到上游事务的 GTID,整个链路断裂。
CHANGE MASTER TO 怎么写:MASTER_AUTO_POSITION=1
是唯一正解
启用 GTID 后,
CHANGE MASTER TO中所有关于日志文件和位置的参数(
MASTER_LOG_FILE、
MASTER_LOG_POS)必须彻底删除,否则报错
ERROR 1777 (HY000): Setting MASTER_LOG_FILE and MASTER_LOG_POS is not allowed when MASTER_AUTO_POSITION = 1。
正确写法只有这一种:
CHANGE MASTER TO MASTER_HOST='192.168.1.10', MASTER_PORT=3306, MASTER_USER='repl', MASTER_PASSWORD='xxx', MASTER_AUTO_POSITION=1;
执行后,从库会自动比对
SELECT @@global.gtid_executed和主库的
gtid_executed集合,找出缺失的 GTID 区间并拉取对应事务。不需要人工解析备份的
gtid_purged值,也不需要
SET GLOBAL gtid_purged=...——除非你做了物理备份恢复,那是另一回事。
常见故障信号:从库卡住、报错 Could not execute Write_rows event
GTID 复制失败时,错误日志往往不直接说“GTID 冲突”,而是表现为 SQL 线程中断、中继日志堆积,或出现类似
Could not execute Write_rows event on table xxx; Duplicate entry '1' for key 'PRIMARY'的报错。这通常意味着: 从库被手动执行过写操作(比如误删/误插),引入了主库没有的 GTID,后续主库发来的同表事务因主键冲突失败 备份恢复时没带
--set-gtid-purged=ON,导致从库的
gtid_executed集合与实际 binlog 内容不一致 跨版本升级后
gtid_mode切换不干净,残留旧 binlog 位置信息
此时不要用
SET GLOBAL sql_slave_skip_counter=1跳过——GTID 模式下该命令被禁用。必须用
SET GTID_NEXT='xxx:yyy'; BEGIN; COMMIT;注入空事务跳过冲突 GTID,操作极容易出错,务必先查清
SELECT * FROM performance_schema.replication_applier_status_by_coordinator;和
SHOW SLAVE STATUS\G中的
Retrieved_Gtid_Set与
Executed_Gtid_Set差异。
真正麻烦的从来不是配置 GTID,而是当它出问题时,你得同时看懂三个集合:
gtid_executed、
gtid_purged、
Retrieved_Gtid_Set之间的包含关系。少看一个,就可能跳错、漏数据、甚至让从库永远追不上主库。
