事务中写关注只能在commitTransaction()时设置,因为事务内所有写操作强制使用{w: 1}且忽略传入的writeConcern,仅commit时的writeConcern控制oplog在多数节点确认后才提交。

事务中写关注只能在 commitTransaction() 时设置,其他地方设了也无效。
为什么不能在 insertOne/updateOne 里传 writeConcern?
事务内部所有写操作(insertOne、updateOne、deleteOne 等)会强制使用 {w: 1},无论你传什么 writeConcern 参数都会被忽略。MongoDB 这么设计是为了避免事务内各操作等待不同确认级别导致状态不一致或死锁。
- 传
{writeConcern: {w: "majority"}}给collection.insertOne()—— 完全没用 - 调用
mongoc_collection_set_write_concern()设置集合级写关注 —— 对事务内操作无效 - 客户端或数据库级全局设置
writeConcern—— 同样不生效
commitTransaction() 的 writeConcern 控制什么?
它只控制事务最终提交那一刻的 oplog 确认行为,即「整个事务日志被多少节点确认后才返回成功」。
-
{w: 1}:主节点写入 oplog 就返回,延迟最低,但主节点宕机且未同步时可能回滚 -
{w: "majority"}:默认值(副本集模式下),多数节点确认后返回 -
{w: "majority", j: true}:多数节点不仅确认,还完成 journal 持久化,安全性最高,延迟也最明显 -
wtimeout值仅在w > 1时起作用,比如{w: 3, wtimeout: 5000}
容易踩的坑:w 值超过可用节点数
如果副本集当前只有 3 个健康节点(含主节点),却设 {w: 5},事务会在 commitTransaction() 卡住,直到超时(默认 60 秒),然后抛出 WriteConcernFailed 错误。
- 务必检查当前副本集成员状态:
rs.status(),重点关注members[n].stateStr和members[n].health - 避免硬编码大数值,尤其在自动扩缩容或节点临时离线场景下
-
"majority"是相对安全的选择,它基于当前有投票权的节点数动态计算
真正起作用的写关注配置,永远只在 session.commitTransaction({ writeConcern: ... }) 这一行;其余任何位置的设置,都是徒劳的干扰项。


















