ApsaraDB for MongoDB提供了Opcounters和Repl Opcounters相關的指標,本文將為您介紹Opcounters指標和Repl Opcounters指標以及相關的常見問題。
Opcounters指標和Repl Opcounters指標支援的執行個體類型,請參見監控項說明。
Opcounters指標
ApsaraDB for MongoDB的監控資訊和效能趨勢功能中均提供了Opcounters指標的相關參數:
Opcounters指標由insert、query、update、delete、getmore和command幾個操作類型組成,該指標展示了mongod或mongos自上次啟動以來啟動並執行不同資料庫操作類型的數量統計。
指標 | 單位 | 說明 |
insert | 個/每秒 | MongoDB每秒插入操作的數量。 |
query | 個/每秒 | MongoDB每秒查詢操作的數量。 |
update | 個/每秒 | MongoDB每秒更新操作的數量。 |
delete | 個/每秒 | MongoDB每秒刪除操作的數量。 |
getmore | 個/每秒 | MongoDB每秒擷取更多操作的數量。 |
command | 個/每秒 | MongoDB每秒命令操作的數量。 |
Opcounters除了會記錄用戶端側發起的操作外,同時也會記錄一些資料庫內部的操作。
指標 | 說明 |
insert |
|
query |
|
update | 與 |
delete |
|
getmore | 主從同步時,資料庫對 |
command |
更多命令請參見Command。 |
Repl Opcounters指標
ApsaraDB for MongoDB的監控資訊中提供了Repl Opcounters指標的相關參數,通常情況下,你僅需要關注從節點上的Repl Opcounters指標。

您也可以在從節點上查看Opcounters指標,該指標主要由以下兩個部分組成:
在從節點上執行的用戶端查詢操作(通過指定相應的readPreference)。
在local庫執行的所有寫入操作(通過主從同步獲得的操作)。
與Opcounters指標類似,Repl Opcounters指標也由insert、query、update、delete、getMore和Command幾個操作類型組成,該指標展示了mongod自上次啟動以來按不同類型匯總的資料庫複寫操作。
指標 | 單位 | 說明 |
insert | 個/每秒 | MongoDB每秒插入操作的數量。 |
query | 個/每秒 | MongoDB每秒查詢操作的數量。 |
update | 個/每秒 | MongoDB每秒更新操作的數量。 |
delete | 個/每秒 | MongoDB每秒刪除操作的數量。 |
getmore | 個/每秒 | MongoDB每秒擷取更多操作的數量。 |
command | 個/每秒 | MongoDB每秒命令操作的數量。 |
Repl Opcounters指標會計算應用在從節點上的所有寫操作,除了Opcounters指標中提及的操作外,還包括以下操作:
會話(session)重新整理觸發的insert和update操作。
TTL索引帶來的刪除操作。
刪除孤立文檔觸發的刪除操作(通常延遲發生在Chunk遷移後)。
寫入系統集合的相關操作,例如可重試寫入(Retryable Writes)會有對
config.transactions的寫入操作。
由於MongoDB在主從複製過程中序列化操作的方式不同,因此,從節點上的Repl Opcounters指標值與主節點上的Opcounters指標值不一樣也是符合預期的。
常見問題
為什麼從節點的Repl Opcounters指標值比主節點的Opcounters指標值高很多?
影響多個文檔的操作(如批量插入、多次更新或多次刪除操作)會被解釋為單個操作。當影響多個文檔的操作複製到從節點時,由於主從複製是基於每個文檔進行的,從節點上的相關Repl Opcounters指標值可能大於在主節點上觀察到的Opcounters指標值。
樣本如下:
更新前檢查Opcounters計數器。
主節點的Opcounters計數器數量顯示為13。
> db.serverStatus().opcounters.update NumberLong(13)從節點的Repl Opcounters計數器數量顯示為11。
> db.serverStatus().opcountersRepl.update NumberLong(11)
主節點執行一次批次更新。通過返回的
modifiedCount欄位可以看到本次批次更新修改了4條文檔。> db.coll.updateMany({x:2},{$set:{x:3}}) { "acknowledged" : true, "matchedCount" : 4, "modifiedCount" : 4 }更新後再次檢查Opcounters計數器。
主節點的Opcounters計數器數量顯示為14。
> db.serverStatus().opcounters.update NumberLong(14)從節點的Repl Opcounters計數器數量顯示為15。
> db.serverStatus().opcountersRepl.update NumberLong(15)
為什麼執行的都是update操作,但從節點的Repl Opcounters指標中卻顯示了不少insert類操作?
可能是因為您的update操作指定了{upsert:true}選項,當期望update的文檔不存在時,會轉為insert操作執行。當oplog裡記錄的是insert操作時,通過主從複製同步到從節點的也將是insert操作,因此Repl Opcounters裡記錄的也就是相應insert操作。
樣本如下:
更新前檢查Opcounters計數器。
主節點的Opcounters計數器中,update數量顯示為33;insert數量顯示為1516。
> db.serverStatus().opcounters { "insert" : NumberLong(1516), "query" : NumberLong(70), "update" : NumberLong(33), "delete" : NumberLong(1043), "getmore" : NumberLong(2662), "command" : NumberLong(4000) }從節點的Repl Opcounters計數器,update數量顯示為24;insert數量顯示為1539。
> db.serverStatus().opcountersRepl { "insert" : NumberLong(1539), "query" : NumberLong(0), "update" : NumberLong(24), "delete" : NumberLong(6), "getmore" : NumberLong(0), "command" : NumberLong(26) }
在主節點上執行帶
{upsert:true}選項的update操作,通過返回的upsertedId欄位可以看到成功插入了1條文檔。> db.coll.updateOne({x:"a"}, {$set:{x:"b"}}, {upsert:true}) { "acknowledged" : true, "matchedCount" : 0, "modifiedCount" : 0, "upsertedId" : ObjectId("64bf72b829907f52b4b363ea") }更新後再次檢查Opcounters計數器。
主節點的Opcounters計數器中,update數量顯示為34;insert數量依舊顯示為1516。
> db.serverStatus().opcounters { "insert" : NumberLong(1516), "query" : NumberLong(70), "update" : NumberLong(34), // 注意這裡計數器的變化 "delete" : NumberLong(1043), "getmore" : NumberLong(2706), "command" : NumberLong(4286) }從節點的Repl Opcounters計數器,update數量依舊顯示為24;insert數量顯示為1540。
> db.serverStatus().opcountersRepl { "insert" : NumberLong(1540), // 注意這裡計數器的變化 "query" : NumberLong(0), "update" : NumberLong(24), "delete" : NumberLong(6), "getmore" : NumberLong(0), "command" : NumberLong(26) }
為什麼主節點上的update操作那麼多,但從節點複製的update操作那麼少?
可能是因為您的商務邏輯裡包含了重複的update操作。重複的update操作由於並沒有發生實際的改動,並不會被複製到從節點上。因此從節點上看到的update運算元量會更少。
樣本如下:
更新前檢查Opcounters計數器。
主節點的Opcounters計數器中update數量顯示為34。
> db.serverStatus().opcounters { "insert" : NumberLong(1516), "query" : NumberLong(70), "update" : NumberLong(34), "delete" : NumberLong(1043), "getmore" : NumberLong(2760), "command" : NumberLong(4609) }從節點的Repl Opcounters計數器中update數量顯示為24。
> db.serverStatus().opcountersRepl { "insert" : NumberLong(1540), "query" : NumberLong(0), "update" : NumberLong(24), "delete" : NumberLong(6), "getmore" : NumberLong(0), "command" : NumberLong(26) }
在主節點上執行update操作,通過返回資訊可以看到並未發生實際修改。
> db.coll.updateMany({x:"ab"},{$set:{x:"cd"}}) { "acknowledged" : true, "matchedCount" : 0, "modifiedCount" : 0 }更新後再次檢查Opcounters計數器。
主節點的Opcounters計數器中update數量顯示為35。
> db.serverStatus().opcounters { "insert" : NumberLong(1516), "query" : NumberLong(70), "update" : NumberLong(35), // 注意這裡計數器的變化 "delete" : NumberLong(1043), "getmore" : NumberLong(2778), "command" : NumberLong(4729) }從節點的Repl Opcounters計數器中update數量依舊顯示為24。
> db.serverStatus().opcountersRepl { "insert" : NumberLong(1540), "query" : NumberLong(0), "update" : NumberLong(24), "delete" : NumberLong(6), "getmore" : NumberLong(0), "command" : NumberLong(26) }
為什麼沒有使用資料庫,但監控上依然能看到一些Opcounters各種類型的操作?
無業務訪問情況下,監控上呈現的少量操作主要由以下幾部分組成:
為了維持MongoDB資料庫正常運轉的一些內部基本操作,比如複本集心跳、主從同步、會話重新整理等。
ApsaraDB for MongoDB資料庫周邊管控組件的一些日常操作,比如探活、監控、監聽等。
為什麼Opcounters裡的指標和執行個體oplog裡按op彙總得到的結果不一樣?
在oplog中,您可以通過op欄位來區分具體的操作類型。常見的取值範圍如下:
kCommand: "c"
kInsert: "i"
kUpdate: "u"
kDelete: "d"
kNoop: "n"事務都是op:c的操作類型,僅在內部的o.applyOps中儲存了事務內包含的所有insert、update、delete操作。如果您僅按oplog的op欄位來進行彙總分析的話,在有事務的情境中,得出的結果會和Opcounters中顯示的結果不一致。更多關於oplog格式的介紹,請參見oplog各欄位的解析。
如您期望統計事務內的具體操作類型數量,可以通過mongo shell用戶端串連MongoDB後執行如下命令。
use local
db.oplog.rs.aggregate([{$match:{"op":"c","ts":{"$gte": Timestamp(1733849400,0)},"o.applyOps":{$exists:true},"o.applyOps.0.op":"u"}},{$count:"count"}])參數說明如下:
Timestamp(1733849400,0):一個查詢oplog格式中的ts時間戳記的下邊界,您需要替換為期望查詢的時間。該時間戳記您可以從local.oplog.rs裡讀取或直接使用UNIX時間戳記。"o.applyOps.0.op":"u":事務oplog中的第一條操作為update,您可以替換為其他動作類型,例如第一條操作為insert時,您可以替換為"o.applyOps.0.op":"i"。{$count:"count"}:僅統計符合要求的oplog條數,您可以使用彙總語句的其他動作符來進行其他分析。
如果您需要查看事務相關的監控指標,可以在ApsaraDB for MongoDB控制台的監控資訊中查看事務運算元指標,具體指標,請參見監控項說明。
樣本如下:
更新前檢查Opcounters計數器。
> db.serverStatus().opcounters { "insert" : NumberLong(4), "query" : NumberLong(6723), "update" : NumberLong(110489), "delete" : NumberLong(3065), "getmore" : NumberLong(222670), "command" : NumberLong(1917525) }在主節點上執行一個僅事務內的寫操作。
// 開啟一個會話 session = db.getMongo().startSession( { readPreference: { mode: "primary" } } ); coll1 = session.getDatabase("mydb1").foo; coll2 = session.getDatabase("mydb2").bar; // 開啟一個事務 session.startTransaction( { readConcern: { level: "local" }, writeConcern: { w: "majority" } } ); // 在事務中執行2個insert操作 try { coll1.insertOne( { abc: 1 } ); coll2.insertOne( { xyz: 999 } ); } catch (error) { // 遇到問題時中止事務 session.abortTransaction(); throw error; } // 提交事務 session.commitTransaction(); session.endSession();更新後再次檢查Opcounters計數器。Opcounters計數器中insert數量由4變成了6。
> db.serverStatus().opcounters { "insert" : NumberLong(6), // 注意這裡計數器的變化 "query" : NumberLong(6728), "update" : NumberLong(110532), "delete" : NumberLong(3067), "getmore" : NumberLong(222823), "command" : NumberLong(1918887) }

