w: "majority" 不等于数据安全落盘,因其仅保证写入多数节点内存oplog,未强制journal持久化;必须配合j: true、启用journal及合理wtimeout才能防宕机丢失。

设置 w: "majority" 本身不能保证数据不丢失,必须配合 j: true 和启用 journal 才能防止掉电、崩溃等场景下的数据丢失。
为什么 w: "majority" 不等于“数据安全落盘”
副本集的 w: "majority" 表示写操作已成功写入大多数有投票权节点的内存(oplog),但这些节点可能尚未将变更刷入磁盘 journal。如果此时主节点或某从节点因 kill -9、断电或 OOM 崩溃,且 journal 未启用或 j: false,那这部分写入就会永久丢失——从节点同步的也是不稳定的内存数据。
常见错误现象:w: "majority" 下仍出现回滚、数据丢失,尤其在故障转移后发现新主节点没有刚写入的文档。
- 只设
w: "majority"→ 数据仅在多数节点内存中,不抗宕机 - 必须加
j: true→ 强制等待 journal 持久化完成 - 服务端 journal 必须开启(默认开启,但单机部署或旧配置可能关闭)
- 计算出的 majority 节点数要包含实际有
votes > 0的成员(隐藏/延迟节点可参与 majority 计算,但不推荐依赖)
w: "majority" 在事务中怎么生效
多文档事务里,writeConcern 只能在 session.startTransaction() 时指定,不能在 insertOne 等单个操作里重复设置;否则会报错 "Cannot specify write concern in both transaction options and operation"。
事务提交时才触发写关注检查,所以:
- 事务内所有写操作共享同一份
writeConcern - 若事务用
{ w: "majority", j: true }提交,但某个从节点 journal 写入失败或超时,整个事务提交失败,客户端收到WriteConcernFailed - 读关注
readConcern: { level: "majority" }在事务中只有搭配该事务的w: "majority"提交才有效;否则读不到“已确认不回滚”的数据
wtimeout 是必选项,不是可选装饰
没设 wtimeout 的 w: "majority" 写操作,在某个从节点卡住、网络分区或临时失联时,会无限期阻塞,拖垮整个应用线程或连接池。
生产环境必须显式设置:
-
wtimeout: 5000(单位毫秒)是较稳妥的起点,覆盖多数网络抖动 - 值为
0等同于未设置,不要用 -
wtimeout只对w > 1或w: "majority"生效,w: 1下无效 - 超时后 MongoDB 不会回滚已成功写入的节点,只返回错误,业务需自行判断是否重试
全局默认写关注比每个操作都设更可靠
靠驱动层或应用代码逐个操作加 writeConcern 容易漏 —— 尤其是 ORM、聚合管道、bulkWrite 里的子操作。用 setDefaultRWConcern 设置全局默认,能让所有未显式覆盖的操作自动继承安全策略。
执行方式(在 admin 库下):
db.runCommand({
setDefaultRWConcern: 1,
defaultRWConcern: { w: "majority", j: true, wtimeout: 5000 }
})
注意:
- 该命令需在副本集主节点上运行
- 设置后立即生效,无需重启
- 已有连接会继承新默认值,但已发出的写请求不受影响
- 如果后续有操作真需要弱一致性(如日志类写入),再单独覆盖
writeConcern: { w: 1 }
真正容易被忽略的是:journal 是否实际生效、wtimeout 是否真的设了、以及事务中写关注的声明位置——这三个点出问题,w: "majority" 就只是个看起来很稳的幻觉。











