判断是否真丢数据而非暂时延迟,须验证三组值:Seconds_Behind_Master=0且IO/SQL线程均为Yes;STOP SLAVE后Retrieved_Gtid_Set与Executed_Gtid_Set完全相等;主从@@global.gtid_executed输出字符串一字不差。

不能靠“快速修复”掩盖问题——GTID模式下主从不一致必须先确认是否真丢失数据,再决定是重置还是重建。 直接执行 SET GTID_PURGED 或 RESET SLAVE ALL 而不验证状态,90% 会把原本可追平的延迟变成永久性数据断裂。
怎么判断是不是真丢了数据,而不是暂时延迟?
别急着修,先看三组值是否真正对齐:
-
SHOW SLAVE STATUS\G中Seconds_Behind_Master必须为0(不是NULL),且Slave_IO_Running和Slave_SQL_Running都是Yes -
Retrieved_Gtid_Set和Executed_Gtid_Set必须完全相等(注意:要STOP SLAVE后再查,避免 SQL 线程正在执行造成瞬时偏差) -
SELECT @@global.gtid_executed;在新主库和所有从库上执行,输出字符串必须一字不差(包括空格、换行、UUID顺序)
只要其中任意一项不满足,就不是“不一致”,而是“还没追上”。强行重置只会让问题更糟。
为什么 CHANGE MASTER TO MASTER_AUTO_POSITION = 1 会报 1236 错误?
这个错误本质是主库已删掉从库还需要的 binlog,不是配置写错了。常见原因有:
- 主库
expire_logs_days设得太小,或人为执行过PURGE BINARY LOGS - 从库曾连过其他主库(比如测试环境),
gtid_executed里混入了别的server_uuid的事务 - 切换前没关掉
log_slave_updates,导致从库 relay log 里的 GTID 没写进自己的 binlog,升主后无法提供完整历史
此时 MASTER_AUTO_POSITION = 1 会失败,因为从库请求的 GTID 在主库 binlog 里根本不存在。不能跳过,也不能硬塞 —— 唯一安全解法是重建从库,或用 SET GTID_PURGED 强制对齐(但前提是确认从库确实没执行过任何额外事务)。
执行 SET GTID_PURGED 前必须做干净的清理
这步最容易出错:只执行 RESET SLAVE ALL 不够,relay log 文件和内存状态仍残留旧位点。
- 先在从库执行
STOP SLAVE;,确认Seconds_Behind_Master是0或NULL - 执行
RESET SLAVE ALL;(注意带ALL,否则master.info和relay-log.info不清) - 查
SHOW VARIABLES LIKE 'relay_log_basename';,手动删掉所有mysql-relay-bin.*文件 - 执行
SET SQL_LOG_BIN = 0;,再执行SET GTID_PURGED = 'xxx:1-100,yyy:1-50';(值必须和主库@@global.gtid_executed完全一致) - 立刻执行
SET SQL_LOG_BIN = 1;,否则后续所有操作都不会记 binlog
如果报 Cannot modify gtid_purged because it is not empty,说明清理不彻底,回退重做。
修复后第一件事不是启同步,而是跑 pt-table-checksum
GTID 对齐只代表“事务序列一致”,不代表“数据内容一致”。内存表(ENGINE=MEMORY)、sql_log_bin=0 下写的语句、触发器/存储过程产生的非确定性结果,都会让 GTID 相同但数据不同。
所以必须立即执行:
pt-table-checksum \ --host=新主库IP \ --user=chkuser \ --password='xxx' \ --databases=myapp \ --replicate=percona.checksums \ --no-check-binlog-format \ --recursion-method=dsn=D=percona,t=dsns \ --max-lag=1
校验结果写入 percona.checksums 表后,再在从库上用 pt-table-sync --print 查差异。不要直接 --execute —— 自动生成的 SQL 可能破坏外键或唯一约束,必须人工 review。
最常被忽略的一点:GTID 模式下,pt-table-checksum 依赖 log_slave_updates=ON 才能在从库上正确比对 checksum 行。如果关了,校验结果永远显示“一致”,实际可能全错。


















