必须重试,但仅限errorLabels含["TransientTransactionError"]的错误(如NotWritablePrimary、PrimarySteppedDown、NetworkTimeout),WriteConflict(code 112)也应重试;Unauthorized等语义错误不可重试。

该不该重试 TransientTransactionError?
必须重试,但只重试明确带 errorLabels: ["TransientTransactionError"] 的错误。常见符合的有:NotWritablePrimary、PrimarySteppedDown、NetworkTimeout。
WriteConflict(错误码 112)虽不自动带该标签,也应重试;而 Unauthorized、InvalidNamespace、DocumentValidationFailure 属于语义错误,重试无意义,应直接失败并排查配置或数据。
用 withTransaction() 还是手写 start/commit?
优先用驱动内置的 withTransaction()。它已封装对 TransientTransactionError 和 UnknownTransactionCommitResult 的识别与重试逻辑,避免手动管理事务状态出错。
手写 session.startTransaction() → 执行 → session.commitTransaction() 容易踩坑:
- 在 session.transaction.state === "TRANSACTION_ABORTED" 后调 commitTransaction(),抛 NoSuchTransaction
- 复用旧 session 的事务状态,但 session 内部事务不可重置
- 忘记在 finally 中调 session.endSession(),导致连接池泄漏
重试次数和退避策略怎么设?
默认 withTransaction() 最多重试 5 次且无退避,生产环境必须干预:
- 外层封装控制重试上限为 2~3 次(长事务建议 2 次,短事务可设 3)
- 采用指数退避:第 1 次失败后等待 100ms,第 2 次后 300ms,第 3 次失败直接 throw 原错误
- 每次重试都新建 ClientSession,整个事务体(含读操作)全部重放,不能只重试 commit 或部分步骤
readConcern 和 writeConcern 怎么配才不拖慢重试?writeConcern: { w: "majority" } 虽安全,但在副本集同步延迟高时会拉长事务生命周期,增加锁冲突和重试概率。
实际配置建议:
- 核心资金类事务保留 { w: "majority" }
- 日志、统计类事务降级为 { w: 1 },降低冲突率
- 避免在事务中用 readConcern: "snapshot"(仅分片集群支持,且加重协调器压力)
- MongoDB 6.0+ 且开启 causal consistency 时,可用 afterClusterTime 替代部分 readConcern: "majority" 场景
withTransaction()。它已封装对 TransientTransactionError 和 UnknownTransactionCommitResult 的识别与重试逻辑,避免手动管理事务状态出错。
手写 session.startTransaction() → 执行 → session.commitTransaction() 容易踩坑:
- 在 session.transaction.state === "TRANSACTION_ABORTED" 后调 commitTransaction(),抛 NoSuchTransaction
- 复用旧 session 的事务状态,但 session 内部事务不可重置
- 忘记在 finally 中调 session.endSession(),导致连接池泄漏
重试次数和退避策略怎么设?
默认 withTransaction() 最多重试 5 次且无退避,生产环境必须干预:
- 外层封装控制重试上限为 2~3 次(长事务建议 2 次,短事务可设 3)
- 采用指数退避:第 1 次失败后等待 100ms,第 2 次后 300ms,第 3 次失败直接 throw 原错误
- 每次重试都新建 ClientSession,整个事务体(含读操作)全部重放,不能只重试 commit 或部分步骤
readConcern 和 writeConcern 怎么配才不拖慢重试?writeConcern: { w: "majority" } 虽安全,但在副本集同步延迟高时会拉长事务生命周期,增加锁冲突和重试概率。
实际配置建议:
- 核心资金类事务保留 { w: "majority" }
- 日志、统计类事务降级为 { w: 1 },降低冲突率
- 避免在事务中用 readConcern: "snapshot"(仅分片集群支持,且加重协调器压力)
- MongoDB 6.0+ 且开启 causal consistency 时,可用 afterClusterTime 替代部分 readConcern: "majority" 场景
writeConcern: { w: "majority" } 虽安全,但在副本集同步延迟高时会拉长事务生命周期,增加锁冲突和重试概率。
实际配置建议:
- 核心资金类事务保留 { w: "majority" }
- 日志、统计类事务降级为 { w: 1 },降低冲突率
- 避免在事务中用 readConcern: "snapshot"(仅分片集群支持,且加重协调器压力)
- MongoDB 6.0+ 且开启 causal consistency 时,可用 afterClusterTime 替代部分 readConcern: "majority" 场景
事务重试不是加个 loop 就完事——关键在错误判别粒度、session 生命周期管控、以及 writeConcern 对重试节奏的隐性影响。漏掉任意一点,都可能把瞬时故障放大成雪崩。


















