手记

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的过滤条件包括

  1. 请求操作类型,insert、update、delete…

  2. 请求对应的connectionId,threadId

  3. 请求是否正在等待锁

  4. 请求执行时间

  5. 请求操作的DB或collection

  6. 请求query的内容

  7. …等等

返回结果如下

{            "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")



作者:微信小程序开发
链接:https://www.jianshu.com/p/cd7b8b6886a6
x


0人推荐
随时随地看视频
慕课网APP