遇到問題:晚10點,DBA在數據庫建立了某collection的索引。在之後的幾分鐘,恰巧有同事訪問某應用,驗證該應用的賬號需從數據庫某表查詢賬號密碼。導致了無法查詢,同事無法登錄上應用。問題便反饋到了運維部。
背景介紹:
Mongodb版本 3.0.2
建索引和collection和賬號查詢collection所在同一臺服務器,不同庫名上。
因使用的是mongodb3.0.2,之前瞭解到3.0是行級鎖,於是dba在建該表索引時,並未加參數background:true。
查原因:
同事無法登錄應用的時間點恰巧是該庫有建索引的時間段。於是主要排查在索引上。後來通過復現問題,確認了該問題。
當主庫開始建索引時,主庫的讀寫是正常的。應用可以正常訪問。但當主庫索引建立完成,Secondary 拉取到一批 oplog 後,從庫開始重放oplog時,此時就有一個特殊 Lock::ParallelBatchWriterMode
的鎖,這個鎖會阻塞所有的讀請求。 這就解釋了爲什麼在建索引之後的 幾分鐘,應用無法訪問。
後查閱了資料:
儘量避免髒讀,等一批 oplog 重放完後,這批數據才允許用戶讀到。
儘量保證同步性能,設想一下,如果重放 oplog 時,使用普通的鎖,那麼 oplog 的重放就需要跟正常的讀寫競爭鎖資源,如果 Secondary 上有大量的讀,那麼勢必會造成備同步逐步跟不上。
雖然3.0版本的讀寫鎖沒有對數據庫造成阻塞,但不要忽略同步鎖 Lock::ParallelBatchWriterMode的影響。
解決問題:
在數據庫儘量空閒的狀態下建索引;
在建索引時,最好還是加上 background:true。