MySQL故障转移中提升副本为主库后出现主副状态不一致的问题求助
看来你在GTID模式下的故障转移操作里踩了个常见的小坑,咱们一步步来分析和解决:
首先,问题核心出在你最后一步重置副本的GTID执行历史和二进制日志这个操作上。在GTID模式下,这类操作(比如RESET MASTER)会直接清空副本的Executed_Gtid_Set,同时重置binlog到起始状态,但这完全是画蛇添足——你已经确认副本追上了主库的所有事务,此时副本的Executed_Gtid_Set应该和原主库完全一致,直接提升为主库即可,根本不需要重置GTID和binlog。
咱们先梳理下GTID模式下正确的故障转移步骤,你可以对照调整:
确认副本完全同步:当看到
Replica_SQL_Running_State显示Replica has read all relay log; waiting for more updates后,一定要先检查副本的Executed_Gtid_Set是否和故障主库完全匹配,执行这条SQL验证:SHOW GLOBAL VARIABLES LIKE 'Executed_Gtid_Set';这是故障转移的核心前提,必须确保两者的GTID集合完全一致。
停止副本的IO_THREAD和SQL_THREAD(这一步你已经做对了)。
直接将副本切换为可读写的主库状态:
SET GLOBAL read_only = OFF; SET GLOBAL super_read_only = OFF;到这里,副本就可以正常作为新主库对外提供服务了,它的
Executed_Gtid_Set会保留和原主库一致的值,binlog也会从当前同步完成的位置继续生成。
那现在怎么修复你当前的问题呢?
你可以把原故障主库的Executed_Gtid_Set值(也就是c219365c-bd04-11ed-b1e2-525400003001:1-4620)手动设置到新主库上:
SET GLOBAL gtid_purged = 'c219365c-bd04-11ed-b1e2-525400003001:1-4620';
执行完成后,新主库的Executed_Gtid_Set就会恢复正确的值,后续新的事务会基于这个GTID集合继续生成,不会再出现状态不一致的问题。
最后补充几个GTID故障转移的注意事项:
- GTID模式下,故障转移的核心逻辑是确保副本执行的GTID完全覆盖原主库的所有GTID,只要这一点满足,数据就不会有问题。
- 重置binlog和GTID历史只适合在初始化全新副本的时候操作,故障转移提升主库时绝对不能这么做。
- 如果之后要把原主库重新加入集群作为新副本,需要先让它通过GTID追上新主库的状态,再重新配置复制关系。
备注:内容来源于stack exchange,提问作者jean-christophe manciot

