記一次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);
總結
以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對我們的支援。