必须先验证三组值是否对齐:Seconds_Behind_Master=0且IO/SQL线程均为Yes、STOP SLAVE后Retrieved_Gtid_Set与Executed_Gtid_Set完全相等、主从@@global.gtid_executed输出一字不差;任一不满足即属未追平而非真丢数据,强行重置将导致永久断裂。

主从切换后数据不一致,不能直接执行 CHANGE MASTER TO 或 RESET SLAVE 就完事——90% 的“修复失败”源于跳过验证、硬塞位点或误判延迟为不一致。
先确认是不是真丢了数据,而不是还没追上
别急着修,三组值必须全部对齐才算真正一致:
-
SHOW SLAVE STATUS\G中Seconds_Behind_Master为0(不是NULL),且Slave_IO_Running和Slave_SQL_Running都是Yes - 执行
STOP SLAVE后,Retrieved_Gtid_Set和Executed_Gtid_Set字符串完全相等(注意空格和 UUID 顺序) - 在新主库和所有从库上分别执行
SELECT @@global.gtid_executed;,输出必须一字不差
任意一项不满足,就说明复制还没完成同步——此时强行重置只会把可追平的延迟变成永久断裂。
GTID 模式下 CHANGE MASTER TO MASTER_AUTO_POSITION = 1 报错 1236 怎么办
这个错误本质是:从库请求的 GTID 在新主库 binlog 里根本不存在。常见原因有:
- 主库
expire_logs_days设得太小,或人为执行过PURGE BINARY LOGS - 从库曾连过其他主库(比如测试环境),
gtid_executed里混入了别的server_uuid的事务 - 切换前没开启
log_slave_updates,导致从库 relay log 里的 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
非 GTID 模式下如何手动对齐 binlog 位点
主从切换后,新主库的 binlog 起始位置和旧从库记录的 Relay_Log_File/Relay_Log_Pos 对不上时,必须人工对齐:
- 在新主库执行
SHOW MASTER STATUS,记下File和Position - 在旧从库执行
STOP SLAVE - 执行
CHANGE MASTER TO MASTER_LOG_FILE = 'mysql-bin.000045', MASTER_LOG_POS = 123456789 - 执行
START SLAVE,再观察Seconds_Behind_Master是否归零
如果从库还有未执行的 relay log,但新主库已删掉对应 binlog(报错 Could not open log file),说明 relay log 缺失上游源头——此时不能跳过,必须重建从库。


















