Skip to content

MongoDB db.currentOp() 详解

db.currentOp() 基础

命令介绍

db.currentOp() 是MongoDB中的一个重要管理命令,用于查看MongoDB实例上当前正在执行的操作。它可以帮助DBA监控数据库活动、识别慢操作和性能瓶颈。

命令语法

javascript
// 查看所有当前操作
db.currentOp()

// 查看特定操作
db.currentOp(<query>)

// 查看详细信息
db.currentOp(<query>, <verbose>)

适用场景

  • 监控数据库实时活动
  • 识别慢查询和性能瓶颈
  • 调试长时间运行的操作
  • 检查锁争用情况
  • 分析数据库负载

db.currentOp() 参数

查询参数

参数类型描述
$allboolean查看所有操作,包括空闲连接
activeboolean只查看活动操作
opstring按操作类型过滤,如"query", "update", "insert"等
nsstring按命名空间过滤,如"test.collection"
querydocument按查询条件过滤
secs_runningnumber查看运行时间超过指定秒数的操作
waitingForLockboolean查看正在等待锁的操作
lockTypestring按锁类型过滤,如"R"(读锁), "W"(写锁)

示例用法

javascript
// 查看所有活动操作
db.currentOp({ active: true })

// 查看运行时间超过5秒的操作
db.currentOp({ secs_running: { $gt: 5 } })

// 查看特定集合的操作
db.currentOp({ ns: "test.users" })

// 查看正在等待锁的操作
db.currentOp({ waitingForLock: true })

// 查看特定操作类型的操作
db.currentOp({ op: "query" })

输出解读

输出结构

javascript
{
  "inprog": [
    {
      "desc": "conn2798",
      "threadId": "140480788209408",
      "connectionId": 2798,
      "client": "127.0.0.1:53628",
      "active": true,
      "opid": 1435637,
      "secs_running": 0,
      "microsecs_running": 123456,
      "op": "command",
      "ns": "admin.$cmd",
      "command": {
        "currentOp": 1,
        "$db": "admin"
      },
      "numYields": 0,
      "locks": {},
      "waitingForLock": false,
      "lockStats": {
        "Global": {
          "acquireCount": {
            "r": NumberLong(1)
          }
        },
        "Database": {
          "acquireCount": {
            "r": NumberLong(1)
          }
        }
      }
    }
  ],
  "ok": 1
}

关键字段解读

  • desc:连接描述符
  • connectionId:连接ID
  • client:客户端IP和端口
  • active:操作是否活动
  • opid:操作ID,用于终止操作
  • secs_running:操作运行时间(秒)
  • op:操作类型(query, update, insert, command等)
  • ns:命名空间(database.collection)
  • command:执行的命令
  • numYields:操作让出的次数
  • locks:锁信息
  • waitingForLock:是否等待锁
  • lockStats:锁统计信息

常见操作类型

操作类型分类

  • query:查询操作
  • update:更新操作
  • insert:插入操作
  • delete:删除操作
  • command:命令操作
  • getmore:获取更多结果
  • none:空闲连接

操作类型详解

  • query:客户端发起的查询请求
  • update:客户端发起的更新请求
  • insert:客户端发起的插入请求
  • delete:客户端发起的删除请求
  • command:客户端发起的命令,如db.currentOp()、db.collection.createIndex()等
  • getmore:游标迭代时获取更多结果
  • none:空闲连接,没有正在执行的操作

锁信息解读

锁类型

  • R:共享锁(读锁)
  • W:排他锁(写锁)
  • r:意向共享锁
  • w:意向排他锁
  • T:全局锁
  • D:数据库锁
  • C:集合锁
  • M:元数据锁

锁状态

  • acquireCount:获取锁的次数
  • acquireWaitCount:等待锁的次数
  • timeAcquiringMicros:获取锁的时间(微秒)
  • deadlockCount:死锁次数

db.currentOp() 最佳实践

监控与诊断

  • 定期运行db.currentOp()监控数据库活动
  • 使用{ active: true, secs_running: { $gt: 10 } }识别慢操作
  • 监控waitingForLock字段识别锁争用
  • 分析lockStats识别锁瓶颈

性能优化

  • 对于长时间运行的查询,考虑添加索引
  • 对于频繁的写操作,考虑分片或优化数据模型
  • 对于锁争用,考虑调整并发度或优化事务

安全操作

  • 使用db.killOp(opid)终止长时间运行的操作
  • 终止操作前确认操作类型和影响范围
  • 定期检查和终止空闲连接

示例脚本

javascript
// 查找并打印慢查询
var slowOps = db.currentOp({
  active: true,
  secs_running: { $gt: 5 },
  op: { $ne: "command" }
}).inprog;

if (slowOps.length > 0) {
  print("慢查询列表:");
  slowOps.forEach(function(op) {
    print("操作ID: " + op.opid);
    print("运行时间: " + op.secs_running + "秒");
    print("操作类型: " + op.op);
    print("命名空间: " + op.ns);
    print("客户端: " + op.client);
    print("查询: " + tojson(op.query));
    print("-" x 50);
  });
} else {
  print("没有发现慢查询");
}

与其他监控工具结合

与 mongostat 结合

  • mongostat 提供全局统计信息
  • db.currentOp() 提供详细的操作信息
  • 结合使用可以全面了解数据库状态

与 mongotop 结合

  • mongotop 提供集合级别的读写统计
  • db.currentOp() 提供操作级别的详细信息
  • 结合使用可以定位具体的性能问题

与 Prometheus + Grafana 结合

  • db.currentOp()的输出导入Prometheus
  • 使用Grafana创建可视化仪表板
  • 实现长期监控和告警

版本差异

MongoDB 3.0 vs 3.2

  • 3.2版本增强了db.currentOp()的输出,包含更多锁信息
  • 3.2版本引入了lockStats字段
  • 3.2版本改进了操作类型的分类

MongoDB 3.2 vs 4.0

  • 4.0版本增强了事务支持,db.currentOp()包含事务信息
  • 4.0版本改进了锁机制,db.currentOp()包含更详细的锁信息
  • 4.0版本引入了stmtId字段,用于标识语句ID

MongoDB 4.0 vs 5.0

  • 5.0版本增强了db.currentOp()的性能
  • 5.0版本改进了输出格式,更易于阅读
  • 5.0版本引入了planSummary字段,包含查询计划摘要

MongoDB 5.0 vs 6.0

  • 6.0版本增强了db.currentOp()的监控能力
  • 6.0版本改进了锁信息的输出
  • 6.0版本引入了更多的操作类型

常见问题(FAQ)

Q1: db.currentOp() 会影响数据库性能吗?

A1: db.currentOp() 本身是一个轻量级命令,对数据库性能影响很小。但在高并发环境下频繁调用可能会产生一定开销,建议合理控制调用频率。

Q2: 如何终止长时间运行的操作?

A2: 可以使用db.killOp(opid)命令终止指定操作。例如:db.killOp(1435637)。注意,终止操作可能会导致数据不一致,应谨慎使用。

Q3: 如何区分读写操作?

A3: 可以通过op字段区分操作类型,或者通过lockType字段区分锁类型。读操作通常使用"R"或"r"锁,写操作通常使用"W"或"w"锁。

Q4: 如何查看锁争用情况?

A4: 可以使用db.currentOp({ waitingForLock: true })查看正在等待锁的操作,或者通过lockStats字段分析锁的获取和等待情况。

Q5: db.currentOp() 可以在分片集群中使用吗?

A5: 是的,db.currentOp()可以在分片集群中使用。在mongos上运行时,会显示所有分片上的操作;在分片上运行时,只显示该分片上的操作。

Q6: 如何查看特定客户端的操作?

A6: 可以使用client字段过滤,例如:db.currentOp({ client: "127.0.0.1:53628" })

Q7: 如何导出 db.currentOp() 的结果?

A7: 可以使用mongoexport或脚本将结果导出为JSON或CSV格式。例如:mongo --eval "printjson(db.currentOp())" > current_op.json

Q8: 如何自动化监控慢操作?

A8: 可以编写脚本定期运行db.currentOp(),识别慢操作并发送告警。例如,每5分钟运行一次脚本,查找运行时间超过10秒的操作,并通过邮件或短信告警。