MongoDB副本集网络分区时,w: "majority"写入会阻塞:多数派Primary等待第二节点确认超时(默认30秒)失败,少数派“假主”直接拒绝写入;事务未提交前数据仅内存暂存,无真正回滚;journal关闭或客户端超时缺失将加剧故障隐蔽性。

写入卡在 w: "majority" 等待确认
MongoDB 副本集默认 writeConcern 是 w: "majority",意思是写操作必须获得大多数节点(比如 3 节点集群需 2 个)的 journal 持久化确认才算成功。一旦发生网络分区,集群被割裂成多数派和少数派子集,少数派节点虽然可能仍自称 "stateStr": "PRIMARY",但它无法与其余节点通信,isMaster 响应中 ismaster 为 true 但 hosts 列表只剩自己——此时它直接拒绝所有 w: "majority" 写入,报错 "errmsg": "not master" 或 InterruptedDueToReplStateChange。而多数派中的 Primary 虽能接收请求,却卡在等待第二个节点响应上,直到超时(默认 30 秒)才失败。
事务提交前不落盘,看似“回滚”实为从未提交
MongoDB 事务不会在网络分区时自动回滚,它根本没机会走到“回滚”那步。事务内所有变更先暂存在会话级内存中,只有调用 commitTransaction() 并成功拿到 w: "majority" 确认后,WiredTiger 才触发 CheckPoint 和 Journal 刷盘。分区期间:
• 多数派 Primary 上的事务一直挂起,数据始终在内存暂存区
• 少数派 “假主” 上的事务直接被拒绝,连暂存都不允许
• 客户端断开或超时后,驱动丢弃会话,内存数据自然清空——这不是回滚,是压根没提交过
journal 关闭会导致“已确认写入”实际丢失
即使某次 w: "majority" 写入看起来成功返回了,如果参与投票的某个 Secondary 节点关闭了 journal(即 storage.journal.enabled: false),它可能把“已确认”状态返回给 Primary,但自身崩溃后无法恢复数据。结果就是:Primary 认为写入已持久化,其他节点却丢了这部分数据,事务最终等效于回滚。这种问题在分区恢复后才会暴露,排查时容易误判为网络问题而非存储配置缺陷。
客户端未设超时会让阻塞更隐蔽
- 默认
writeConcernTimeoutMS是 30000(30 秒),但很多驱动或应用层没显式设置连接/操作超时 - 结果就是:一个
commitTransaction()请求在多数派 Primary 上挂起 30 秒才失败,期间线程/连接被占住,下游服务出现雪崩式超时 - 真正该检查的不是“为什么写不进”,而是“为什么等这么久才报错”——重点看客户端侧的
socketTimeoutMS和serverSelectionTimeoutMS是否合理
w: "majority" + journal 全链路生效,缺一不可;任何一环配置松动(比如某个节点关 journal、客户端没设超时、驱动覆盖了 writeConcern),都会让故障表现变得难以归因。


















