共计 2848 个字符,预计需要花费 8 分钟才能阅读完成。
这篇文章给大家分享的是有关 Mongo 中如何使用 killOp 干掉 Long Running Operation 的内容。丸趣 TV 小编觉得挺实用的,因此分享给大家做个参考,一起跟随丸趣 TV 小编过来看看吧。
详解:
详解 currentOp()
gechongrepl:PRIMARY db.currentOp()
{
inprog : [
{
opid : 6222,
active : true,
secs_running : 3,
microsecs_running : NumberLong(3662328),
op : getmore ,
ns : local.oplog.rs ,
query : {
},
client : 192.168.91.132:45745 ,
desc : conn5 ,
threadId : 0x7f1370cb4700 ,
connectionId : 5,
waitingForLock : false,
numYields : 0,
lockStats : {
timeLockedMicros : {
r : NumberLong(141),
w : NumberLong(0)
},
timeAcquiringMicros : {
r : NumberLong(16),
w : NumberLong(0)
}
}
}
]
}
opid : 6222,# 进程号
active : true,# 是否活动状态
secs_running : 3,# 操作运行了多少秒
microsecs_running : NumberLong(3662328),
op : getmore ,# 操作类型,包括 (insert/query/update/remove/getmore/command)
ns : local.oplog.rs ,# 命名空间
query : {},# 如果 op 是查询操作,这里将显示查询内容;也有说这里显示具体的操作语句的
client : 192.168.91.132:45745 ,# 连接的客户端信息
desc : conn5 ,# 数据库的连接信息
threadId : 0x7f1370cb4700 ,# 线程 ID
connectionId : 5,# 数据库的连接 ID
waitingForLock : false,# 是否等待获取锁
numYields : 0,
lockStats : {
timeLockedMicros : {# 持有的锁时间微秒
r : NumberLong(141),# 整个 MongoDB 实例的全局读锁
w : NumberLong(0)},# 整个 MongoDB 实例的全局写锁
timeAcquiringMicros : {# 为了获得锁,等待的微秒时间
r : NumberLong(16),# 整个 MongoDB 实例的全局读锁
w : NumberLong(0)}# 整个 MongoDB 实例的全局写锁
MongoDB 提供了 killOp 请求,用于干掉运行时间很长的请求,killOp 通常需要与 currentOp 组合起来使用;先根据 currentOp 查询到请求的 opid,然后根据 opid 发送 killOp 的请求。
currentOp
currentOp 的使用,参考官方文档
currentOp 会将后端 Mongod 上正在执行的请求都列出来,也可根据查询条件(如请求类型,请求是否正在等待锁,请求操作的 DB 或 collection)来进行过滤。
例 1:查询所有正在等待锁的写操作
db.currentOp(
{
waitingForLock : true,
$or: [ { op : { $in : [ insert , update , remove ] } },
{ query.findandmodify : { $exists: true } }
]
}
)
例 2:查询所有操作 db1 并且执行时间已超过 3s 的请求
db.currentOp(
{
active : true,
secs_running : { $gt : 3 },
ns : /^db1\./
}
)
currentOp 的过滤条件包括
请求操作类型,insert、update、delete…
请求对应的 connectionId,threadId
请求是否正在等待锁
请求执行时间
请求操作的 DB 或 collection
请求 query 的内容
…
killOp
currentOp 的输出结果里,每个请求包含一个 opid 字段,有了 opid,就可以发送 killOp 来干掉对应的请求。
db.killOp(opid)
要了解 killOp 的意义,需要先搞清楚几个问题
客户端到 Monogd Server 连接断掉后,连接上执行的请求是否会立即结束?
比如你通过 mongo shell,发送了一个 createIndex 的请求,给某个包含 1000w 个文档的集合建立索引,这个请求会耗时很久,你想提前中止请求,Ctrl- C 停掉了 mongo shell,此时 mongo shell 到 server 的连接会关闭掉。
但后端 createIndex 的请求(MongoDB 每个连接的请求由一个对应的线程来处理)不会立即结束,而是会一直执行下去,直到 createIndex 结束,给客户端发送应答时,发现连接已经关闭,然后线程才退出。
为了让 createIndex 早点结束,你就需要 killOp 来帮忙,通过 currentOp 找到 craeteIndex 请求的 opid,然后发送 killOp,createIndex 会在下个『检查点』就结束执行,整个线程退出。
发送 killOp 后,请求是否会立即结束?
killOp 的实现原理如下
每个连接对应的服务线程存储了一个 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 等。
感谢各位的阅读!关于“Mongo 中如何使用 killOp 干掉 Long Running Operation”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!