发现多个 primary 即确认脑裂,应立即切流禁写;仅存 secondary 时需 force 强制重配使其升主;真假 primary 须比对 optimedate 和 lastheartbeatrecv;恢复后必查 writeconcernmajorityjournaldefault 是否启用 journal。

看到多个 stateStr: "PRIMARY" 就该立刻停写
这不是选举延迟,而是已确认脑裂。此时任意 w: "majority" 写操作会卡住或报 NotMaster,但 w: 1 仍可能静默写入少数派节点——数据就此分裂。别等自动恢复,先切走流量,禁止新写入。
用 rs.reconfig(..., {force: true}) 强制重订多数派
当只剩一个存活节点且为 SECONDARY,无法执行 rs.add() 或 rs.remove(),必须靠强制重配:
- 连上那个存活节点,在 mongo shell 中执行
cfg = rs.conf() - 清空
cfg.members数组,只保留该节点(例如cfg.members = [cfg.members[2]]) - 确保该节点的
priority≥ 1、votes= 1,且hidden和arbiterOnly都为false - 运行
rs.reconfig(cfg, {force: true})—— force 是关键,否则会因“无法联系多数节点”拒绝执行
成功后该节点会立即升为 PRIMARY,此时才能用 rs.add("host:port") 逐个加回健康节点。
optimeDate 和 lastHeartbeatRecv 比对真伪主
rs.status() 显示两个 PRIMARY?别信表面状态。真正有效的 PRIMARY 必须满足:
-
optimeDate接近当前时间(落后 >30 秒基本可判为孤立) -
lastHeartbeatRecv持续更新(停滞说明已失联) -
health: 1 的成员数 ≥ ⌊N/2⌋+1(如 4 节点集群至少要有 3 个 health: 1)
若某节点 optimeDate 明显滞后且 lastHeartbeatRecv 停在分区发生时刻,它就是假 PRIMARY,即使 ismaster 返回 true,也不该被写入。
恢复后必须校验 writeConcernMajorityJournalDefault
脑裂恢复后查到“刚写的数据没了”,大概率是 journal 关闭导致的回滚。检查每个节点配置:
- 运行
db.runCommand({ getCmdLineOpts: 1 }),确认storage.journal.enabled为true - 检查副本集全局设置:
db.adminCommand({ getParameter: 1, writeConcernMajorityJournalDefault: 1 }) - 若返回
"writeConcernMajorityJournalDefault" : false,需在启动参数中显式设为true并重启节点
没开 journal 的节点,哪怕进了 majority,崩溃后也会丢数据——这个坑在恢复后最容易被忽略。











