外观
MongoDB db.currentOp() 详解
db.currentOp() 基础
命令介绍
db.currentOp() 是MongoDB中的一个重要管理命令,用于查看MongoDB实例上当前正在执行的操作。它可以帮助DBA监控数据库活动、识别慢操作和性能瓶颈。
命令语法
javascript
// 查看所有当前操作
db.currentOp()
// 查看特定操作
db.currentOp(<query>)
// 查看详细信息
db.currentOp(<query>, <verbose>)适用场景
- 监控数据库实时活动
- 识别慢查询和性能瓶颈
- 调试长时间运行的操作
- 检查锁争用情况
- 分析数据库负载
db.currentOp() 参数
查询参数
| 参数 | 类型 | 描述 |
|---|---|---|
$all | boolean | 查看所有操作,包括空闲连接 |
active | boolean | 只查看活动操作 |
op | string | 按操作类型过滤,如"query", "update", "insert"等 |
ns | string | 按命名空间过滤,如"test.collection" |
query | document | 按查询条件过滤 |
secs_running | number | 查看运行时间超过指定秒数的操作 |
waitingForLock | boolean | 查看正在等待锁的操作 |
lockType | string | 按锁类型过滤,如"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秒的操作,并通过邮件或短信告警。
