直接执行db.currentOp({"secs_running":{"$gt":5},"active":true,"lsid":{"$exists":true}})可精准筛选运行超5秒、带会话ID的活跃事务,避免瞬时事务干扰;事务阻塞未必表现为waitingForLock为true,需结合secs_running和lsid重复性判断;db.killOp()无法终止事务,应使用db.killSessions()杀会话。

怎么用db.currentOp()快速揪出阻塞事务
直接执行 db.currentOp({ "secs_running": { "$gt": 5 }, "active": true, "lsid": { "$exists": true } }),就能筛出运行超 5 秒、且带会话 ID 的活跃事务。别用 secs_running: { "$gt": 0 },刚启动的事务(比如 secs_running 是 0.1)会混入大量噪音,干扰判断。
常见错误是只查 "waitingForLock": true,但事务阻塞未必表现为“等待锁”——它可能正在执行一个没索引的 update,waitingForLock 是 false,secs_running 却一路涨到 60+ 秒,这才是真瓶颈。
- 加
"transaction.state": "inProgress"可进一步确认确实是事务,而非普通命令 - 如果返回结果里
lsid高度重复,而txnNumber不变,说明同一个会话卡在事务里没提交 - 配合
"ns": /^your_db\./限定数据库,避免被其他库的慢操作淹没
为什么db.killOp()杀不掉事务
db.killOp() 只能终止具体操作(opid),但事务生命周期由会话(lsid)管理。一个会话里可以跑多个 find、update,killOp 干掉其中一个,transaction.state 仍是 "inProgress",锁照常持有。
硬杀 opid 后发现事务还在 currentOp 里?正常。这不是 bug,是设计使然。
- 真正该做的是从应用层调用
session.commitTransaction()或session.abortTransaction() - 若应用已失联,可用
db.killSessions([{"id": "<lsid_value>"}])</lsid_value>杀整个会话(需 admin 权限) -
db.killSessions()才是终结事务的正确方式,db.killOp()只适合杀单个长查询或建索引
Compass 里怎么看事务是否在阻塞写入
Compass 的 Performance 面板看不到事务详情,它只聚合 serverStatus 数据,而事务状态不在其中。想确认是不是事务拖慢写入,得下钻:
- 打开 Shell 标签页,执行
db.currentOp({ "secs_running": { "$gt": 5 }, "op": { "$in": ["update", "insert", "delete"] } }),重点看lsid和secs_running - 再查
db.currentOp({ "waitingForLock": true }),如果返回一堆写操作,且它们的lsid和上面查到的某个长事务一致,就是它在持锁 - 集合视图里对慢操作右键 → “Explain Plan”,若出现
TRANSACTION上下文,说明执行计划受事务隔离影响(如不能用某些索引)
别依赖 connections_current 或 active ops 数值——它们高只说明连接多或操作多,不等于事务阻塞。
Profiler 能不能帮上忙
能,但要懂怎么过滤。Profiler 默认不记录 commitTransaction 或 abortTransaction,只记事务内真实执行的命令(find、update 等),关键识别字段是 lsid 和 txnNumber。
开启后查慢日志:db.setProfilingLevel(1, { slowms: 100 }),然后查 db.system.profile.find({ "lsid": { "$exists": true } }).sort({ "ts": -1 }).limit(10)。
- 如果某条
update的millis很高,且带lsid,就说明这个事务里的更新本身慢,不是锁的问题 - 若同个
lsid下多条操作都慢,优先检查第一个操作——大概率是它缺索引,导致后续操作排队等锁 - 别指望 Profiler 显示 “事务开始时间”,它不存那个时间戳;
ts字段是命令完成时间,往前推millis才是大致执行起点
事务真正难搞的地方不在语法,而在它把多个操作绑进一个会话上下文——lsid 是唯一贯穿始终的线索,所有排查动作都得围着它转。漏掉这个,就等于在黑屋子里找开关。


















