1 db.currentOp() 方法
1.1 db.currentOp() 概述
官网说明如下:
https://www.mongodb.com/docs/manual/reference/method/db.currentOp/
db.currentOp()方法会返回数据库实例当前操作的信息,是数据库命令currentOp的封装。
语法:
db.currentOp( )
operations 是可选项。 可以是boolean 或者 document 类型。 当指定true时,会包含空闲连接和系统操作。当指定查询条件的filter文档时,则只返回匹配条件的操作。
db.currentOp()支持的filter文档有如下3种类型:
- “$ownOps”: 布尔型,当设置为true时,只返回当前用户的操作信息。
- “$all”:布尔型,当设置为true时,返回所有操作的信息,包括空闲连接和系统操作。
- :根据output fields指定过滤条件。 当”$all”: true 和 output fields 同时存在时,只有”$all”: true生效。
完整的output fields 参考官网链接:
https://www.mongodb.com/docs/manual/reference/command/currentOp/#std-label-currentOp-output-fields
db.currentOp(true) 和 db.currentOp( { “$all”: true } ) 是等效的,查询结果相同。
Db.currentOp() 和 database profiler 一样对所有的CRUD操作输出相同的基本诊断信息,具体如下:
- aggregate
- count
- delete
- distinct
- find (OP_QUERY and command)
- findAndModify
- getMore (OP_GET_MORE and command)
- insert
- mapReduce
- update
这些操作也同样会记录在慢查询日志中(slowOpThresholdMs )。
MongoDB 4.4 数据库分析器(Database Profiler)
https://www.cndba.cn/dave/article/107982
1.2 db.currentOp() 示例
以下代码查询正在等待lock的所有写操作信息:
db.currentOp(
{
"waitingForLock" : true,
$or: [
{ "op" : { "$in" : [ "insert", "update", "remove" ] } },
{ "command.findandmodify": { $exists: true } }
]
}
)
以下代码查询所有活动但没有工作(active but no yield)的操作:
db.currentOp(
{
"active" : true,
"numYields" : 0,
"waitingForLock" : false
}
)
以下代码查询db1 数据库上所有执行超过3秒的活动会话:
db.currentOp(
{
"active" : true,
"secs_running" : { "$gt" : 3 },
"ns" : /^db1/./
}
)
以下代码查询正在创建索引的操作:
db.adminCommand(
{
currentOp: true,
$or: [
{ op: "command", "command.createIndexes": { $exists: true } },
{ op: "none", "msg" : /^Index Build/ }
]
}
)
输出结果列的描述参考官网链接:
https://www.mongodb.com/docs/manual/reference/command/currentOp/#std-label-currentOp-output-fields
2 db.killOp()方法
2.1 db.killOp() 概述
官网说明如下:
https://www.mongodb.com/docs/manual/reference/method/db.killOp/
db.killOp(opid) 方法根据指定的操作ID 来中断操作。 可以使用db.currentOp()来查看opid。
中断正在运行的操作是一项非常危险的操作,只能用db.killOp() 方法来中断客户端的操作,不能用来中断数据库内部的操作。
2.2 Sharded Cluster 中的db.killOp() 操作
Shard cluster 环境下,读写操作可能会在多个shard 上有会话信息,所以killOp()需要同时kill 掉这些会话。 MongoDB 4.0 后在一个shard节点上执行时,会同步kill 掉其他节点上的操作,之前的版则需要手工分别kill 这些操作。
2.2.1 Kill Read Operations
2.2.1.1 MongoDB 4.0+
从MongoDB 4.0 开始,db.killOp() 可以在mongos上运行,并且可以kill在所有shard上运行的 read 操作。
2.2.1.1.1 在mongos 实例上执行
在客户端连接的mongos 上(必须在这个节点)执行聚合查询获取opid:
use admin
db.aggregate( [
{ $currentOp : { allUsers: true, localOps: true } },
{ $match : <filter condition> } // Optional. Specify the condition to find the op.
// e.g. { op: "getmore", "command.collection": "someCollection" }
] )
然后根据查询到的opid ,在对应的mongos上进行kill:
db.killOp( )
2.2.1.1.2 在shard 实例上执行
也可以在操作运行的shard 实例上查找并kill read 操作。 MongoDB 4.0+ 会自动将kill 操作发送到其他shard 节点和mongos 实例。
在执行操作的shard 节点上查找opid:
use admin
db.aggregate( [
{ $currentOp : { allUsers: true } },
{ $match : <filter condition> } // Optional. Specify the condition to find the op.
// e.g. { op: "getmore", "command.collection": "someCollection" }
] )
在shard 实例上执行db.killOp()命令:
db.killOp( )
MongoDB 4.0+ 会将kill 操作发送到其他shard 节点和mongos 节点。
2.2.1.2 MongoDB 3.6 之前的版本
在MongoDB 3.6 之前的sharded cluster中,如果要kill 一个查询操作,还必须kill掉关联的shard节点上的查询操作。
在mongos 实例上执行聚合管道命令:$currentOp 来查找查询操作的shard 节点。
use admin
db.aggregate( [
{ $currentOp : { allUsers: true } },
{ $match : <filter condition> } // Optional. Specify the condition to find the op.
// e.g. { op: "getmore", "command.collection": "someCollection" }
] )
$currentOp 命令会以/”shardName : opid on that shard”的格式返回opids信息:
{
"shard" : "shardB",
..
"opid" : "shardB:79014",
...
},
{
"shard" : "shardA",
..
"opid" : "shardA:100813",
...
},
在mongos 节点执行db.killOp()来kill 所有shard的操作。
db.killOp(“shardB:79014”);
db.killOp(“shardA:100813”);
2.2.2 Kill Write Operations
2.2.2.1 Within a Session
从MongoDB 3.6 开始,MongoDB驱动程序将除未确认的写操作外的所有操作与server session关联。
Server Sessions
https://www.mongodb.com/docs/manual/reference/server-sessions/
如果写操作已经关联到了server session,那么可以在mongos 节点执行killSessions 命令来kill 跨shard的写操作。
2.2.2.1.1 MongoDB 4.0+
在mongos 节点执行聚合管道命令$currentOp来查找lsid (logical session id).
use admin
db.aggregate( [
{ $currentOp : { allUsers: true, localOps: true } },
{ $match : <filter condition> } // Optional. Specify the condition to find the op.
// e.g. { "op" : "update", "ns": "mydb.someCollection" }
] )
根据lsid,在mongos 节点,执行killSessions 命令来kill 所有分片上的操作:
db.adminCommand( { killSessions: [
{ "id" : UUID("80e48c5a-f7fb-4541-8ac0-9e3a1ed224a4"), "uid" : BinData(0,"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=") }
] } )
2.2.2.1.2 MongoDB 3.6
在mongos 节点或者分别在每个shard上执行$currentOp 命令来查找lsid (logical session id):
use admin
db.aggregate( [
{ $currentOp : { allUsers: true } },
{ $match : <filter condition> } // Optional. Specify the condition to find the op.
// e.g. { "op" : "update", "ns": "mydb.someCollection" }
] )
根据lsid,在mongos 节点,执行killSessions 命令来kill 所有分片上的操作:
db.adminCommand( { killSessions: [
{ "id" : UUID("80e48c5a-f7fb-4541-8ac0-9e3a1ed224a4"), "uid" : BinData(0,"47DEQpj8HBSa+/TImW+5JCeuQeRkm5NMpJWZG3hSuFU=") }
] } )
2.2.2.2 Without a Session
如果写操作没有关联到server session,那么必须kill 所有shards上的写操作。
在mongos 节点执行$currentOp命令查找所有shard上运行的查询操作:
use admin
db.aggregate( [
{ $currentOp : { allUsers: true } },
{ $match : <filter condition> } // Optional. Specify the condition to find the op.
] )
$currentOp命令会以”shardName : opid on that shard “的格式返回opids的信息:
{
"shard" : "shardB",
..
"opid" : "shardB:79214",
...
},
{
"shard" : "shardA",
..
"opid" : "shardA:100913",
...
},
然后在mongos 节点执行killOp()命令来kill 所有分片上的操作:
db.killOp(“shardB:79014”);
db.killOp(“shardA:100813”);
版权声明:本文为博主原创文章,未经博主允许不得转载。