好久没更新mongo运维这块知识了,这次介绍 db.currentOp与db.killOp命令
数据库优化方法有很多,但所有数据库优化都离不开慢查询优化。mysql、mongodb都可以开启慢查询,来对数据库查询进行分析。开启慢查询日志,对性能会有一定的影响。mongoDB
有时我们只想临时看下慢查询日志,应该如何处理。
这时,我们可以用到mongdb的db.currentOp
命令 ,他可以列出当前真正跑的op相关信息。
1.查看目前正在执行的所有查询语句
db.currentOp();
2.查询所有操作xxx集合并且执行时间已超过3s
的请求
db.currentOp(
{
"active" : true,
"secs_running" : { "$gt" : 3 },
"ns" : /^xxx\./
}
)
3. 当然,如果我当前db集群有非常多的集合,我也可以不限制xxx集合
db.currentOp(
{
"active" : true,
"secs_running" : { "$gt" : 3 }
}
)
currentOp的过滤条件包括
- 请求操作类型,insert、update、delete…
- 请求对应的connectionId,threadId
- 请求是否正在等待锁
- 请求执行时间
- 请求操作的DB或collection
- 请求query的内容
- …等等
返回结果如下
{
"desc" : "conn44266",
"threadId" : "140419266524928",
"connectionId" : 44266,
"client" : "10.10.68.209",
"active" : true,
"opid" : 4495651,
"secs_running" : 25,
"microsecs_running" : NumberLong(25459008),
"op" : "command",
"ns" : "xxxxx",
"query" : {
"count" : "c74dc2de71",
"query" : {
"video" : {
"$exists" : true
},
"_isdel" : 0,
"deleted" : {
"$ne" : true
},
"verify" : {
"$ne" : false
}
}
},
"planSummary" : "IXSCAN { video: 1 }",
"numYields" : 189,
"locks" : {
"Global" : "r",
"Database" : "r",
"Collection" : "r"
},
"waitingForLock" : false,
"lockStats" : {
"Global" : {
"acquireCount" : {
"r" : NumberLong(380)
}
},
"Database" : {
"acquireCount" : {
"r" : NumberLong(190)
}
},
"Collection" : {
"acquireCount" : {
"r" : NumberLong(190)
}
}
}
}
当我们知道某条语句是锁库的罪魁祸首的时候,我们就可以通过另一条语句,干掉对应的请求。
killOp 停止正在执行的查询
用法:
db.killOp(opid)
目前Mongodb手册,还未有一次清掉当前所有查询,文档地址:https://docs.mongodb.com/manual/reference/method/db.killOp/
执行后返回
{ "info" : "attempting to kill op", "ok" : 1 }
db.killOp(opid)的实现原理如下
每个连接对应的服务线程存储了一个killPending的字段,当发送killOp时,会将该字段置1;请求在执行过程中,可以通过不断的调用OperationContext::checkForInterrupt()来检查killPending是否被设置,如果被设置,则线程退出。
一个请求要支持killOp,必须在请求的处理逻辑里加上checkForInterrupt()检查点才行,否则即使发送了killOp,也只能等待请求完全处理完毕线程才会退出。
比如createIndex的处理逻辑里包含了类似如下的代码,在createIndex的循环过程中,一旦killPending被置1了,createIndex的执行可以在当前循环结束时退出。
while (!createIndexFinished) {
createIndexForOneElement();
checkForInterupt();
}
所以发送killOp后,请求要执行到下一个『检查点』线程才会退出,MongoDB在很多可能耗时长的请求中,都加入了checkForInterrupt()检查点,如创建索引,repair database,mapreduce、aggregation等。
批量一次清楚当前慢查询
上面说还未有一次清掉当前所有查询, 不过我们可以通过手动写脚本实现。此脚本由diggzhang大神贡献。文章链接:http://yangcongchufang.com/kill-mongo-ops.html
实现功能:传入自己的IP地址,强制关停自己的异常查询。
打开家目录下的.mongorc.js
拷贝下面的killMyRunningOps
函数进去,重新打开mongoshell
即可加载这个函数(mongoshell
启动时会预读这个文件)。
➜ ~ cat ~/.mongorc.js
killMyRunningOps = function (clientIp) {
var currOp = db.currentOp();
for (op in currOp.inprog) {
if (clientIp == currOp.inprog[op].client.split(":")[0]) {
db.killOp(currentOp.inprog[op].opid)
}
}
}
用法很简单,知道自己IP后,调用这个函数:
> killMyRunningOps("12.23.32.21")
评论 (0)