脑裂后须立即隔离原主库写入:在primary集群执行fencewrites(),原主库设super_read_only=on并持久化,校验gtid或位点一致后再重建复制,同时stop slave防止日志刷屏。

主从切换后出现脑裂,本质是写入被分流到两个“主库”,必须立刻隔离原主库写入,否则数据会持续分裂、不可逆损坏。
为什么fenceWrites()执行失败?
常见报错:ERROR: Unable to fence Cluster from write traffic: operation not permitted on REPLICA Clusters。这不是权限问题,而是你正在一个REPLICA Cluster上执行fenceWrites()——该命令只允许在PRIMARY Cluster上调用。如果你误在从集群上运行,MySQL Shell 会直接拒绝。确认当前集群角色:运行cluster.status(),检查role字段是否为HA且primary指向本集群。若为REPLICA,需切换到新主集群的 MySQL Shell 连接中再执行。
如何真正阻断原主库的写入?
不能只依赖应用层切流量。原主库一旦未被强制只读,任何残留连接(如监控脚本、DBA手动登录、未重启的应用连接池)都可能写入新数据,导致后续无法对齐。必须双管齐下:
- 在原主库上立即执行:
SET GLOBAL super_read_only = ON;(注意不是read_only,super_read_only可阻止SUPER权限用户写入) - 同步修改配置文件
my.cnf,添加super_read_only = ON并重启,防止实例重启后恢复可写 - 检查是否有活跃写连接:
SELECT * FROM performance_schema.threads WHERE TYPE = 'FOREGROUND' AND PROCESSLIST_COMMAND IN ('Query', 'Execute') AND PROCESSLIST_INFO NOT LIKE '%SELECT%';,对非查询连接主动KILL
数据同步恢复前必须校验什么?
不要急着CHANGE MASTER TO重搭复制。先确认新主库和原主库之间是否存在已丢失但未察觉的事务:
- 若启用GTID:在新主库执行
SELECT @@GLOBAL.gtid_executed;,在原主库执行SELECT @@GLOBAL.gtid_purged;,二者必须完全相等;若有差值,说明原主库有未同步到新主库的事务,需人工提取binlog补入 - 若未启用GTID:比对新主库的
Exec_Master_Log_Pos与原主库的Position(来自SHOW MASTER STATUS),两者必须一致;不一致则用mysqlbinlog --start-position=... --stop-position=...提取缺失binlog并重放 - 跳过
Seconds_Behind_Master = 0的假象:并行复制下该值可能为0但仍有事务在relay log中未执行,务必检查Slave_SQL_Running_State是否为Slave has read all relay log; waiting for more updates
重建复制关系时最容易漏掉的一步
很多人在新主库上执行完CHANGE MASTER TO就认为完成了,却忘了关闭原主库上的复制线程。这会导致原主库仍尝试向已下线的旧主(或空地址)发起IO连接,日志刷屏error connecting to master,消耗资源且干扰排查。正确操作是:
- 在原主库上执行:
STOP SLAVE;(不是RESET SLAVE ALL,后者会清空复制元数据,影响后续回切) - 确认
Slave_IO_Running和Slave_SQL_Running均为No - 如需保留反向复制能力(例如未来回切),可在新主库上配置指向原主库的复制关系,但务必确保原主库已
super_read_only = ON且无写入
脑裂后的修复窗口极短,所有操作必须在写入停止后的5分钟内完成判断和执行。任何延迟都会扩大数据差异,使CHECKSUM TABLE或pt-table-checksum校验变得低效甚至失效。











