mongo 杀掉慢的程序killMyRunningOps("12.23.32.21") #####这个是客户端的ip
mongodb运维(3) db.currentOp与db.killOp命令
好久没更新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 }
image.png
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") #####这个是客户端的ip