GTID主从不一致需彻底重置:先STOP SLAVE,RESET SLAVE ALL,手动删除relay log,再SET GTID_PURGED对齐主库gtid_executed,最后CHANGE MASTER TO MASTER_AUTO_POSITION=1。

为什么 SHOW SLAVE STATUS 里的 Executed_Gtid_Set 和主库对不上
主从 GTID 不一致,本质是复制链路中事务记录发生了断裂或跳变。常见原因不是网络丢包,而是人为执行了 SET GLOBAL sql_slave_skip_counter=1、START SLAVE UNTIL、或在从库上直接写了数据(哪怕只是一条 INSERT)。GTID 要求“每个事务有唯一 ID 且不可跳过”,一旦从库执行了未在主库 gtid_executed 中出现的事务,Executed_Gtid_Set 就会多出一段 UUID:1-N,导致后续 CHANGE MASTER TO MASTER_AUTO_POSITION = 1 失败。
- 检查是否从库写入过:运行
SELECT * FROM performance_schema.replication_applier_status_by_coordinator;,看APPLYING_TRANSACTION是否为空或异常 - 确认主库当前 GTID:在主库执行
SELECT @@global.gtid_executed; - 确认从库已执行 GTID:在从库执行
SELECT @@global.gtid_executed;,对比是否包含主库输出的全部区间
重置前必须停掉从库复制并清空 relay log
不能边复制边改 GTID,否则 relay_log_info_repository = TABLE 下的状态表和实际文件会错位,RESET SLAVE ALL 也不够干净。正确顺序是:
- 在从库执行
STOP SLAVE; - 确认
Seconds_Behind_Master为NULL或0,再执行RESET SLAVE ALL;(注意带ALL,它会删掉master.info和relay-log.info文件) - 手动删除残留 relay log:查
SHOW VARIABLES LIKE 'relay_log_basename';,然后rm -f /path/to/mysql-relay-bin.*(路径以实际配置为准) - 重启 mysqld 进程(可选但推荐),确保内存状态彻底清零
用 SET GTID_PURGED 强制对齐主库状态
这是最关键的一步。从库不能自己“猜”该从哪继续,必须显式告诉 MySQL:“我只认主库当前已执行的这些 GTID”。操作前提是主库已开启 enforce_gtid_consistency = ON 且 gtid_mode = ON。
- 在主库执行
FLUSH LOGS;,再执行SELECT @@global.gtid_executed;,记下完整输出(如aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-100) - 在从库执行前,先关掉二进制日志:
SET SQL_LOG_BIN = 0; - 执行
SET GTID_PURGED = 'aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa:1-100';(值必须完全一致,不能多空格、不能少分号) - 立刻执行
SET SQL_LOG_BIN = 1;,否则后续所有操作都会被跳过 - 如果报错
Cannot modify gtid_purged because it is not empty,说明之前没清干净,回退到上一步重做RESET SLAVE ALL+ 删除 relay log
CHANGE MASTER TO ... MASTER_AUTO_POSITION = 1 后仍报错怎么办
典型错误是 The slave is connecting using CHANGE MASTER TO MASTER_AUTO_POSITION = 1, but the master has purged binary logs containing GTIDs that the slave requires。这表示主库 binlog 已被清理,缺失从库需要的事务。
- 检查主库
expire_logs_days或binlog_expire_logs_seconds,确认是否太小(建议至少设为 7 天) - 临时恢复:在主库执行
SHOW BINARY LOGS;,看最老的 binlog 文件名;用mysqlbinlog --base64-output=decode-rows -v解析它,确认是否还包含从库缺失的 GTID 区间 - 若已丢失,只能重新全量同步:用
mysqldump --all-databases --single-transaction --set-gtid-purged=ON导出,导入从库后再次执行SET GTID_PURGED(值取 dump 文件头部的SET @@GLOBAL.GTID_PURGED) - 避免下次发生:从库加监控项,告警
Retrieved_Gtid_Set != Executed_Gtid_Set或Seconds_Behind_Master > 300
GTID 重置不是“一键修复”,关键在于每一步都验证状态是否真正归零——尤其是 gtid_executed、gtid_purged 和 relay log 文件三者必须严格一致。少验证一个,后面就可能卡在 Waiting for source to send event 里半天不动。


















