You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MongoDB 5.0多文档事务错误码112排查与复现咨询

MongoDB 5.0 写入冲突问题解答

问题1:为何集群日志无WriteConflict(112)错误记录?如何配置仅记录此类错误?

日志未记录的原因

  1. 错误返回层级问题:你看到的错误是由mongos路由节点返回的,但实际的WriteConflict发生在分片节点(mydatashard:27017),若你只查看了mongos或其他非目标分片的日志,自然找不到对应记录。
  2. 默认日志策略:MongoDB 5.0中,WriteConflict(112)属于预期的并发冲突类 transient 错误,默认不会将这类客户端可见的冲突写入节点日志,仅会直接返回给发起请求的客户端。

配置仅记录错误码112的日志

MongoDB 4.4+支持通过logFilter过滤特定错误码,结合日志组件级别调整实现精准记录,需在发生冲突的分片节点上配置:

动态配置(无需重启节点)

在分片节点的mongosh中执行:

db.adminCommand({
  setParameter: 1,
  // 调整命令、写入组件的日志级别,确保能捕获到冲突事件
  logComponentVerbosity: {
    command: { verbosity: 1 },
    write: { verbosity: 1 }
  },
  // 过滤仅记录错误码112的日志
  logFilter: {
    filter: { code: 112 },
    action: "log"
  }
})

配置文件持久化(mongod.conf)

systemLog:
  verbosity: 0
  component:
    command:
      verbosity: 1
    write:
      verbosity: 1
  filter:
    - filter: { code: 112 }
      action: log

配置后,仅错误码112的WriteConflict日志会被输出,其他无关日志不会被记录。


问题2:如何正确复现错误码112(WriteConflict)场景?

你当前的复现方式得到251(NoSuchTransaction)错误,是因为事务在更新阶段已因冲突被终止,导致commit时返回事务不存在的错误。要复现112错误,需让冲突发生在事务内的操作执行阶段,而非commit阶段。

正确复现步骤

  1. 先准备测试数据:
db.cities.insert({name: "test", x: 0})
  1. 使用两个会话模拟并发冲突:
    会话1(先执行):
var session1 = db.getMongo().startSession();
session1.startTransaction({ 
  readConcern: { level: "snapshot" }, 
  writeConcern: { w: "majority" } 
});
var coll = session1.getDatabase('test').getCollection('cities');
// 查询文档获取快照,持有锁资源
coll.findOne({ name: "test" });
// 等待5秒,给会话2执行更新的时间
sleep(5000);
// 执行更新,此时会话2的更新已触发冲突
coll.update({ name: "test" }, { $set: { x: 1 } });
try {
  session1.commitTransaction();
} catch(e) {
  print(JSON.stringify(e));
}
session1.endSession();

会话2(在会话1执行findOne后立即启动):

var session2 = db.getMongo().startSession();
session2.startTransaction({ 
  readConcern: { level: "snapshot" }, 
  writeConcern: { w: "majority" } 
});
var coll = session2.getDatabase('test').getCollection('cities');
// 直接执行更新,与会话1的快照锁产生冲突
coll.update({ name: "test" }, { $set: { x: 2 } });
try {
  session2.commitTransaction();
} catch(e) {
  print(JSON.stringify(e));
}
session2.endSession();

关键注意事项

  • 若使用分片集群,需确保测试文档被路由到同一个分片(比如将name设为分片键,或文档哈希值落在同一分片)。
  • 冲突的核心是两个操作同时修改同一文档,且其中一个操作持有快照或锁资源,导致另一个操作触发WriteConflict。

内容的提问来源于stack exchange,提问作者R2D2

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 05:25:06