应立即执行db.currentop({ "secs_running": { "$gt": 5 }, "active": true })查长事务,重点关注secs_running、numyields和microsecs_running;需结合lsid与transactionnumber筛选真实事务,通过comment定位业务来源,并分别检查主从节点。

直接用 db.currentOp() 查,别等报错再动手——90% 的长事务在超时前就已卡住,只是没人看。
查 active 且运行超 5 秒的事务
长事务最典型的特征是 secs_running 高、active 为 true,且没在等待锁(waitingForLock 通常为 false)。别只盯着 secs_running > 60,很多业务逻辑卡在外部调用上,5 秒已是危险信号。
- 执行
db.currentOp({ "secs_running": { "$gt": 5 }, "active": true }),重点关注返回结果里的secs_running、numYields和microsecs_running -
numYields持续增长说明查询正在反复让出 CPU,大概率是全表扫描或索引失效 - 如果
microsecs_running远大于secs_running × 1e6,说明事务内有阻塞式 I/O(比如 await HTTP 请求) - 避免用
db.currentOp({ "secs_running": { "$gt": 60 } })—— 等到 60 秒才查,服务可能已经雪崩
过滤掉无关操作,只看真正属于事务的会话
默认 db.currentOp() 返回大量后台任务和空闲连接,必须加条件筛出真实事务上下文。关键字段是 lsid(逻辑会话 ID)和 transactionNumber,两者同时存在才表示该操作处于事务中。
- 推荐命令:
db.currentOp({ "secs_running": { "$gt": 2 }, "lsid": { "$exists": true }, "transactionNumber": { "$exists": true } }) - 如果返回结果里
secs_running高但transactionNumber缺失,说明事务早已结束,只是客户端没调endSession(),连接被占着不放 - 注意区分
type: "op"(普通操作)和type: "txn"(事务协调操作),后者出现在分片集群的 coordinator 节点上,secs_running高意味着跨分片事务卡在 prepare 阶段
结合 comment 字段快速定位业务来源
如果你已在事务写操作中统一透传了 comment(如 JSON.stringify({ trace_id: "req-abc123" })),那它会原样出现在 currentOp 输出里,这是唯一能绕过日志直接关联代码路径的方式。
- 确保 MongoDB ≥ 5.0、驱动 ≥ 4.0,且 profiling 级别 ≥ 1(否则
comment不记录) - 查法:
db.currentOp({ "comment": { "$regex": "trace_id.*abc123" } }) - 如果
comment字段为空,不要急着改代码——先确认是否所有写操作(insertOne、updateOne、deleteMany)都显式传了comment选项;session.startTransaction()本身不接受comment参数,传了也无效 - 注意
comment最长 1024 字节,别塞整个 request body,否则截断后无法匹配
别漏掉副本集 secondary 上的“影子长事务”
主节点上看不到的长事务,可能正卡在从节点同步链路里。secondary 同步慢会导致 oplog 积压,而 db.currentOp() 默认只查当前节点——你连问题在哪台机器上都不知道。
- 必须分别登录每个
members[n]节点,执行相同currentOp查询;不能只查 primary - 特别关注
rs.status()中optimeDate落后超过 30 秒的成员,再对其执行db.currentOp({ "secs_running": { "$gt": 5 } }) - secondary 上出现长事务,常见原因是磁盘 IO 慢(
iostat -x 1看%util)、网络延迟高(mtr测主从间延迟)、或开启了priority: 0却没设hidden: true,导致选举异常影响同步节奏
真正难处理的不是“怎么查”,而是查到之后不敢 kill —— 因为不知道它卡在哪个环节。所以每次上线新事务逻辑,务必在测试环境跑一遍 currentOp + explain("executionStats") 组合拳,把 totalDocsExamined 和 nReturned 的比值记下来,这才是你线上敢动手的底气。











