w:majority 要求写操作被大多数投票节点的 oplog 持久化后才确认,能防止单点故障导致已确认写入丢失,但需配置合理、多数节点在线且启用 journal:true,否则仍可能丢数据。

什么是 w:majority,它真能防止数据丢失?
w:majority 不是“写入所有节点才返回成功”,而是要求写操作被大多数投票节点(voting members)的 oplog 持久化后才确认。它能防止单点故障导致的已确认写入丢失,但前提是副本集配置合理、多数节点在线且具备持久化能力。
常见误解:设了 w:majority 就绝对不丢数据——错。如果主节点在写入 oplog 前崩溃,且未同步到任何从节点,该写入仍会丢失;w:majority 保障的是“已确认写入”在多数节点上落盘后的可恢复性。
- 必须启用
journal: true(默认开启),否则w:majority只保证写入内存中的oplog,而非磁盘 - 副本集节点数建议为奇数(如 3 或 5),避免脑裂时无法达成多数
- 非投票节点(
votes: 0)或延迟节点(priority: 0+slaveDelay)不参与majority计算
如何在事务中强制使用 w:majority
MongoDB 事务默认继承会话的写关注(writeConcern),而驱动默认会话通常用 w:1。你不能在 session.startTransaction() 里直接传 writeConcern,必须显式设置会话级写关注。
以 Node.js 驱动为例:
const session = client.startSession();
// 必须在 startTransaction 前设置
session.options.writeConcern = { w: 'majority', j: true };
await session.withTransaction(async () => {
await collection.insertOne({ x: 1 }, { session });
await collection.updateOne({ x: 1 }, { $set: { y: 2 } }, { session });
});
-
j: true强制 journal 刷盘,与w:majority配合才能真正防丢 - Python PyMongo 同理:用
session.start_transaction(write_concern=WriteConcern(w='majority', j=True)) - Java 驱动需调用
session.setWriteConcern(WriteConcern.MAJORITY),再startTransaction()
为什么事务里设了 w:majority 还出现超时或回滚?
典型现象:WriteConcernFailed: Cannot satisfy write concern 或事务因 MaxTimeMSExpired 中断。根本原因是:事务期间某节点宕机、网络分区,或多数节点因负载高/磁盘慢未能及时落盘 journal。
- 检查
rs.status().members是否有节点状态异常(如RECOVERING、UNKNOWN) - 确认所有投票节点都启用了 journal(
storage.journal.enabled: true)且磁盘 I/O 正常 - 避免在低配环境(如单机多实例伪集群)中依赖
w:majority,此时“多数”可能只是同一块慢盘上的多个进程 - 事务内操作越长、涉及文档越多,写入扩散到多数节点所需时间越长,超时风险越高
要不要全局配置 defaultWriteConcern?
可以,但不推荐用于生产事务系统。在 mongod.conf 中设 replication.defaultWriteConcern: { w: "majority", j: true } 会让所有写操作(包括非事务写)强制走 majority,容易掩盖问题:
- 集合级写操作(如
createIndex)可能意外阻塞,影响运维响应 - 某些只读场景误发写命令(如误用
update而非find)也会被拖慢 - 测试/开发环境若复用相同配置,会导致本地单节点启动失败(无法满足 majority)
更稳妥的做法是:仅在明确需要强一致性的业务会话中按需设置 writeConcern,其他写操作保持默认 w:1。
真正关键的不是参数本身,而是理解它依赖的整个链路:journal 是否刷盘、节点是否健康、网络是否稳定、事务粒度是否合理——任何一个环节松动,w:majority 就只是个纸面承诺。











