主从切换后binlog与relay_log_info不匹配时,需手动重置位点:先查新主库show master status,再在旧从库stop slave并change master to指定新binlog文件和位置,最后start slave并校验数据一致性。

主库 binlog 位置和从库 relay_log_info 不匹配怎么办
主从切换后最常见的不一致,是新主库的 binlog 起始位置和旧从库记录的 Relay_Log_File/Relay_Log_Pos 对不上——比如从库还在读 mysql-relay-bin.000012,但新主库已经滚动到 mysql-bin.000045,且旧 relay log 文件已被清理。这时 START SLAVE 会直接报错 Could not find first log file name in binary log index file 或卡在 Waiting for master to send event 却无实际同步。
必须人工对齐位点,不能依赖 CHANGE MASTER TO MASTER_AUTO_POSITION = 1(GTID 模式下才有效,且要求原主从都开启 GTID)。
- 先在新主库执行
SHOW MASTER STATUS,记下File和Position - 在旧从库停掉复制:
STOP SLAVE - 用新主库的位点重置从库:
CHANGE MASTER TO MASTER_LOG_FILE = 'mysql-bin.000045', MASTER_LOG_POS = 123456789 - 确认
Seconds_Behind_Master归零后再启同步:START SLAVE
从库有未执行完的 relay log,但主库已删掉对应 binlog
典型场景:主库磁盘紧张,expire_logs_days 设得太小,或手动 PURGE BINARY LOGS;而从库因延迟没来得及消费完 relay log,切换后找不到原始 binlog,IO_THREAD 启动失败,错误信息通常是 Got fatal error 1236 from master when reading data from binary log: 'Could not open log file'。
这不是数据丢失,而是 relay log 缺失上游源头。此时不能强行跳过,否则可能跳过关键 DDL 或事务。
- 检查从库是否还有未执行的 relay log:
SHOW SLAVE STATUS\G看Relay_Log_File和Relay_Log_Pos是否指向一个真实存在的文件 - 若 relay log 文件存在但对应主库 binlog 已删,唯一安全做法是重建从库:用新主库当前快照 +
mysqldump --single-transaction --master-data=2或物理备份恢复 - 切勿使用
SET GLOBAL sql_slave_skip_counter = 1(已弃用)或gtid_next跳过——这会破坏事务一致性,尤其涉及多表更新或外键时
GTID 模式下 RESET SLAVE 导致 gtid_purged 错乱
执行 RESET SLAVE ALL 后,从库的 gtid_purged 会被清空,但新主库的 gtid_executed 可能包含大量已删除 binlog 对应的 GTID。如果此时不做校验就 CHANGE MASTER,从库会拒绝同步,报错 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。
核心是让从库的 gtid_purged 包含新主库缺失日志的 GTID 范围,又不能多加、不能重复。
- 在新主库查完整 GTID 集:
SELECT @@global.gtid_executed - 在旧从库执行:
RESET SLAVE ALL,然后SET GLOBAL gtid_purged = 'xxx-yyy-zzz:1-10000'(值必须严格等于新主库的gtid_executed) - 注意:该语句只允许在
gtid_executed为空时执行,所以RESET SLAVE ALL必须在前,且不能有任何事务写入 - 再
CHANGE MASTER TO ... MASTER_AUTO_POSITION = 1,START SLAVE
重置后如何快速验证数据一致性
跑完 START SLAVE 并看到 Seconds_Behind_Master: 0 不代表数据一致——只是复制线程没延迟,但可能早先就漏了某些事务(比如切换前 IO 线程已断连但 SQL 线程还在跑)。必须做校验。
不要依赖 pt-table-checksum 在主从间边同步边校验,它会在主库写 checksum 表,而切换后主库角色已变,容易干扰业务。
- 先确认从库
Slave_SQL_Running_State是Slave has read all relay log; waiting for more updates,且Retrieved_Gtid_Set == Executed_Gtid_Set - 挑几个关键业务表,用
CHECKSUM TABLE t1分别在主从上执行,比对结果(注意:该命令会锁表,选低峰期) - 更轻量的方式:抽样对比主从的
SELECT COUNT(*), MIN(id), MAX(id), SUM(length(content)) FROM t1,覆盖行数、主键范围、内容体积三个维度 - 如果发现差异,优先查
SHOW SLAVE STATUS\G中的Last_SQL_Errno和Seconds_Behind_Master历史波动,而不是直接重做从库——有些不一致是切换瞬间的正常窗口期
最易被忽略的是:重置从库时没关掉监控告警,导致 Seconds_Behind_Master 归零后,告警系统仍按旧阈值持续误报;或者应用层缓存没清,以为数据已同步,其实缓存里还是老数据。











