Mongodb
MongoDB Locking - 讀起來非常非常慢
這是 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 將在看到磁碟故障時嘗試讓步)。查看MMS或mongostat中的頁面錯誤指標以了解其中的趨勢,事實上,MMS 將是了解此實例整體上隨著時間推移發生的情況的好地方。
上述方面的變化
$in
應該對此有所幫助,但可能只會讓罐子走下坡路。如果你要對大量數據進行聚合,它要麼需要在 RAM 中,這種東西速度很快,要麼你需要把它放到輔助設備上,這樣緩慢的磁碟訪問就不會拖累所有東西它。