1. 程式人生 > 資料庫 >記一次Mongodb中admin資料庫導致的事故

記一次Mongodb中admin資料庫導致的事故

前言

MongoDB副本集預設會建立local、admin資料庫,local資料庫主要儲存副本集的元資料,admin資料庫則主要儲存MongoDB的使用者、角色等資訊。

Mongodb的gridfs一次插入資料的時候會自動建立幾個索引,我們程式裡面的賬號沒有createIndex許可權,我需要手動建立一下。結果連線到mongo伺服器之後忘記執行use xxxdb來切換資料庫了,於是在admin資料庫裡面建立了一個索引,結果匯出一邊的程式報出來很多驗證問題。

Mongo的admin資料庫太脆弱了,只是建立一個索引就掛了。長個教訓,以後千萬不要手動修改它,更不要用admin儲存資料。

反思一下,這次操作失誤其實爆出我平時一些不好的習慣。

首先,連線mongo應該指定目標資料。而我之前都是連線到admin,然後用use切換到目標資料庫。這樣難免會忘記。

$ # 錯誤使用
$ mongo ourdomain.com/admin -u tom -p tompass
$ # 正確的使用
$ mongo ourdomain.com/mydb -u tom -p tompass --authenticationDatabase admin

第二,錯誤的在admin資料庫執行createIndex,返回的結果明確顯示索引建立成功。

{
  "createdCollectionAutomatically" : true,"numIndexesBefore" : 1,"numIndexesAfter" : 2,"ok" : 1,...
}

但是我忽略了,繼續在正確的資料庫建立索引。不然可以早一些發現問題。

最後,建立索引應該自動化,比如gridfs這種對md5,filename建立索引的。

慎用admin資料庫

當Mongod啟用auth選項時,使用者需要建立資料庫帳號,訪問時根據帳號資訊來鑑權,而資料庫帳號資訊就儲存在admin資料庫下。

mongo-9551:PRIMARY> use admin
switched to db admin
mongo-9551:PRIMARY> db.getCollectionNames()
[ "system.users","system.version" ]
  • system.version儲存authSchema的版本資訊
  • system.users儲存了資料庫帳號資訊
  • 如果使用者建立了自定義的角色,還會有system.roles集合

使用者可以在admin資料庫下建立任意集合,儲存任何資料,但強烈建議不要使用admin資料庫儲存應用業務資料,最好建立新的資料庫。

admin資料庫裡的system.users、system.roles2個集合的資料,MongoDB會cache在記憶體裡,這樣不用每次鑑權都從磁碟載入使用者角色資訊。目前cache的維護程式碼,只有在保證system.users、system.roles的寫入都序列化的情況下才能正確工作,詳情參考官方issue SERVER-16092

從程式碼中我們可以看出,MongoDB將將admin資料庫上的意向寫鎖(MODE_IX)直接升級為寫鎖(MODE_X),也就是說admin資料庫的寫入操作的鎖級別只能到DB級別,不支援多個collection併發寫入,在寫入時也不支援併發讀取。如果使用者在admin資料庫裡儲存業務資料,則可能遭遇效能問題。

if (supportsDocLocking() || enableCollectionLocking) { 
if (supportsDocLocking() || enableCollectionLocking) {
+
+ // The check for the admin db is to ensure direct writes to auth collections
+ // are serialized (see SERVER-16092).
+ if (_id == resourceIdAdminDB && !isRead) {
+ _mode = MODE_X;
+ }
+
_lockState->lock(_id,_mode); 

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對我們的支援。