transactionLifetimeLimitSeconds仅限制事务上下文存续时长(默认60秒),不监控执行、不中断操作、不约束prepare阶段;真正影响跨分片事务超时的是maxTimeMS(需在startTransaction中设置)及prepare阶段锁等待、会话缓存不同步、管理命令阻塞等实际瓶颈。

调 transactionLifetimeLimitSeconds 不能解决你遇到的“事务卡住几十秒后报 TransactionTooOld”问题——它只管事务上下文存续时间,不管 prepare 阶段卡在哪、锁等多久、网络断没断。
transactionLifetimeLimitSeconds 到底管什么
这个参数是服务端对「事务从 startTransaction 开始到被协调分片主动 abort」的硬性兜底时长,默认 60 秒。它不参与任何实时监控,也不中断正在执行的操作:
- 某个分片上
db.collection.updateOne()因缺索引慢了 25 秒,事务仍算active,该参数不触发 abort -
mongos和一个 shard 失联,prepare 请求发不出去,事务状态卡在starting,这个状态压根不计入计时 - 客户端调了
session.commitTransaction(),消息发出去了但没收到响应,服务端其实已 commit 成功——这属于UnknownTransactionCommitResult,和生命周期无关 - 跨分片事务最终受所有参与分片中
transactionLifetimeLimitSeconds的最小值约束(木桶效应),改一个 shard 的没用
maxTimeMS 是唯一能被事务主操作响应的超时控制
maxTimeMS 是客户端可设、且 coordinator shard 会实际遵守的超时参数,但它只约束「协调者本地上主操作的执行时间」,不是整个两阶段提交的保险丝:
- 必须在
session.startTransaction({ maxTimeMS: 12000 })里传入,事后调session.transactionOptions无效 - 实测耗时 × 1.5 设值:比如测试环境从 start 到 commit 平均耗时 8 秒,就设
12000,别拍脑袋填300000 - 跨分片场景下,
maxTimeMS对其他分片的 prepare 响应延迟、网络往返、commit 消息丢失完全无感 - Node.js 驱动里,如果事务内混了未建索引的
countDocuments()或带upsert: true但无唯一索引的写入,maxTimeMS会很快被吃掉
真正卡住事务的三个高频点
分布式事务超时,90% 以上都卡在 prepare 阶段。排查要直击现场,而不是调参:
- 连每个 shard 执行
db.currentOp({ "secs_running": { "$gt": 2 }, "waitingForLock": true }),看有没有操作在等锁超过 2 秒 - 逐个连接 shard 执行
db.runCommand({getLastError: 1}),比对返回里的txnNumber是否一致;不一致说明逻辑会话缓存不同步 - 在每个 shard 上运行
db.adminCommand({refreshLogicalSessionCacheNow: 1})强制刷新;生产环境建议把logicalSessionCacheRefreshPeriodMS从默认300000改为30000并滚动重启 - 避开
sh.setBalancerState(false)、sh.moveChunk()等管理命令高峰期发起事务——它们会短暂阻塞 prepare 流程
事务超时不是配置问题,是协调链路某处失联或阻塞的信号。盯着 transactionLifetimeLimitSeconds 调,就像给发烧病人量血压却不查感染源。


















