Mongo中如何使用killOp干掉Long Running Operation

67次阅读
没有评论

共计 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”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,让大家可以学到更多知识,如果觉得文章不错,可以把它分享出去让更多的人看到吧!

正文完
 
丸趣
版权声明:本站原创文章,由 丸趣 2023-07-24发表,共计2848字。
转载说明:除特殊说明外本站除技术相关以外文章皆由网络搜集发布,转载请注明出处。
评论(没有评论)