Mongodb

MongoDB Locking - 讀起來非常非常慢

  • May 22, 2013

這是 db.currentOp() 的輸出:

> db.currentOp()
{
   "inprog" : [
       {
           "opid" : 2153,
           "active" : false,
           "op" : "update",
           "ns" : "",
           "query" : {
               "name" : "Run_KPIS",
               "profile" : "totals"
           },
           "client" : ":34140",
           "desc" : "conn127",
           "threadId" : "0x7f1d0f03c700",
           "connectionId" : 127,
           "locks" : {
               "^cached_data" : "W"
           },
           "waitingForLock" : true,
           "numYields" : 0,
           "lockStats" : {
               "timeLockedMicros" : {

               },
               "timeAcquiringMicros" : {

               }
           }
       },
       {
           "opid" : 2154,
           "active" : false,
           "op" : "getmore",
           "ns" : "",
           "query" : {

           },
           "client" : ":34129",
           "desc" : "conn118",
           "threadId" : "0x7f1e32785700",
           "connectionId" : 118,
           "locks" : {
               "^cached_data" : "R"
           },
           "waitingForLock" : true,
           "numYields" : 0,
           "lockStats" : {
               "timeLockedMicros" : {

               },
               "timeAcquiringMicros" : {

               }
           }
       },
       {
           "opid" : 1751,
           "active" : true,
           "secs_running" : 98,
           "op" : "query",
           "ns" : "cached_data.webtraffic",
           "query" : {
               "mapreduce" : "webtraffic",
               "map" : function () {
       if (this.Pages)
           for (var i in this.Pages)
               if (i.match(/(\/blogs\/|\/news\/)/))
                   emit({
                       'page':i,
                       'profile':this.Profile
                   },this.Pages[i]);
   },
               "reduce" : function (k,vals) {
       for(var i=0,sum=0;i<vals.length;sum+=vals[i++]);
       return sum;
   },
               "out" : {
                   "inline" : 1
               },
               "query" : {
                   "$or" : [
                       {
                           "Profile" : "MEMBER"
                       },
                       {
                           "Profile" : "WEB"
                       }
                   ]
               }
           },
           "client" : ":34111",
           "desc" : "conn112",
           "threadId" : "0x7f1d1768d700",
           "connectionId" : 112,
           "locks" : {
               "^" : "r",
               "^cached_data" : "R"
           },
           "waitingForLock" : false,
           "msg" : "m/r: (1/3) emit phase M/R: (1/3) Emit Progress: 801/830 96%",
           "progress" : {
               "done" : 801,
               "total" : 830
           },
           "numYields" : 148,
           "lockStats" : {
               "timeLockedMicros" : {
                   "r" : NumberLong(183690739),
                   "w" : NumberLong(0)
               },
               "timeAcquiringMicros" : {
                   "r" : NumberLong(92296403),
                   "w" : NumberLong(0)
               }
           }
       }
   ]
}

我對所有相關集合都有索引,但是當上述操作執行時,從我們的 MongoDB 讀取仍然存在巨大延遲。

再次讀取數據庫可能需要大約 5 分鐘。

上面的 map reduce 函式會導致這個讀鎖嗎?如果是這樣,我如何在集合上執行非鎖定映射減少?

奇怪的是,MongoDB 仍然接受連接,只是不允許我們在上述操作執行時進行查詢。

編輯說這是 Mongo 版本 2.4.1。

首先,這裡正在執行查詢。它對$or同一欄位的兩個值使用運算符。如果這是典型的,請將其更改為$in操作員(如這裡推薦的那樣)。這應該有很大幫助 - 當您使用 $or 時,您正在並行執行兩個查詢並合併結果,當您使用時,您執行單個查詢。

接下來,由於這是一個內聯Map Reduce 作業,我建議在輔助設備上執行它(如果您還沒有),並在其他地方執行任何具有更實時要求的應用程序。您可以通過多種方式執行此操作,但最靈活的是基於標籤的讀取首選項

在解釋currentOp()輸出方面,大寫字母代表全域鎖,這可能是阻止事情的原因(儘管它會嘗試讓步),您還可以看到它花了很多時間嘗試獲取鎖第一名。我假設這代表了對相關數據的大型表掃描,並且數據並不完全適合 RAM,而是從磁碟中調入。因此,該查詢的 yield 數量(MongoDB 將在看到磁碟故障時嘗試讓步)。

查看MMSmongostat中的頁面錯誤指標以了解其中的趨勢,事實上,MMS 將是了解此實例整體上隨著時間推移發生的情況的好地方。

上述方面的變化$in應該對此有所幫助,但可能只會讓罐子走下坡路。如果你要對大量數據進行聚合,它要麼需要在 RAM 中,這種東西速度很快,要麼你需要把它放到輔助設備上,這樣緩慢的磁碟訪問就不會拖累所有東西它。

引用自:https://serverfault.com/questions/496414