mongo 殺掉慢的程序killMyRunningOps("12.23.32.21") #####這個是客戶端的ip


mongodb運維(3) db.currentOp與db.killOp命令

2018.08.12 23:55 113瀏覽
 字號

好久沒更新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")   #####這個是客戶端的ip

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM