db.currentOp() 默认查不到事务细节,因其设计面向操作层而非事务会话层,事务内读写被归并为"op":"command",关键字段如"lsid""txnNumber"需显式投影;6.2+已弃用,应改用$currentOp聚合阶段配合过滤与投影。

直接用 db.currentOp() 查事务状态在 MongoDB 6.2+ 已不推荐,且默认根本看不到事务内部操作 —— 因为事务中的多数操作被包裹在 command 类型下,"op": "command",而关键字段如 "transactionNumber"、"lsid"、"txnNumber" 不在默认输出里,必须显式投影。
为什么 db.currentOp() 默认查不到事务细节
MongoDB 从 4.0 引入多文档事务,但 db.currentOp() 的设计初衷是监控“操作层”(query/insert/update),不是事务会话层。事务启动后,其内部读写会被归并为一个 command 操作,比如 "command": {"commitTransaction": 1} 或 {"abortTransaction": 1},而真正执行的 find/update 等动作不会单独出现在 inprog 列表中。
-
db.currentOp()在 6.2+ 已标记为弃用,底层实际调用$currentOp聚合阶段,但该阶段默认不展开事务上下文 - 即使加
{"active": true},也只会看到事务 commit/abort 命令本身,看不到它锁了哪些文档、卡在哪条语句上 -
"lsid"(逻辑会话 ID)和"txnNumber"是识别同一事务的关键,但它们不出现在基础字段里,需手动$project
如何用 $currentOp 聚合阶段查真实事务状态
绕过 db.currentOp() 辅助方法,直接用聚合管道调用 $currentOp,才能拿到完整事务字段。注意:这要求你有 inprog 权限,且不能在 M0/M2/M5 Atlas 免费集群上运行。
- 查所有活跃事务会话:
db.adminCommand({ aggregate: 1, pipeline: [ { $currentOp: { allUsers: true } }, { $match: { "secs_running": { $gt: 0 }, "lsid": { $exists: true }, "txnNumber": { $exists: true } } }, { $project: { "lsid": 1, "txnNumber": 1, "secs_running": 1, "ns": 1, "command": 1, "waitingForLock": 1, "locks": 1 } } ], cursor: {} }) - 只看未提交的事务(排除已 commit/abort 的命令):
{"command.commitTransaction": { $exists: false }, "command.abortTransaction": { $exists: false }} - 结合锁信息定位阻塞源:
"waitingForLock": true+"locks": { "Global": "w", "Database": "w" }表示该事务正持写锁阻塞他人
db.currentOp() 还能用吗?哪些场景别踩坑
可以临时用,但必须清楚它的局限性和权限陷阱。
- 在本地开发或 Community 版本上,
db.currentOp({"active": true, "secs_running": {$gt: 5}})能快速揪出慢事务命令,但无法告诉你这个命令属于哪个应用连接 - 在 Atlas 上,M10 及以上集群支持
$currentOp,但 M0/M2/M5 明确禁用 —— 此时db.currentOp()直接报错Command currentOp not allowed - 用
db.currentOp({ "$ownOps": true })只能看到当前 shell 会话的操作,对排查其他应用发起的长事务无效 - 不要依赖
"query"字段判断事务内容:事务里的查询会被压缩成"command": {"find": "orders", ...},原始 filter 不展开
真正要监控事务,得靠组合手段
单靠 db.currentOp() 或 $currentOp 都不够。生产环境需要把三类数据串起来:
- 应用层:在开启事务时打日志,记录
lsid.id和开始时间(pymongo 的session._server_session.session_id可取到) - 数据库层:用
$currentOp抓lsid+txnNumber+secs_running,再关联应用日志 - 基础设施层:配合
mongostat --host xxx --port xxx看txn列的每秒事务数,突增往往意味着事务堆积
最容易被忽略的是 lsid 的二进制格式 —— 它在 shell 里显示为 BinData(4, "..."),但 Python/pymongo 中是字典结构,跨系统比对时得 base64 解码后比对,否则永远对不上。











