《MongoDB無法啟動,如何恢復數據?》要點:
本文介紹了MongoDB無法啟動,如何恢復數據?,希望對您有用。如果有疑問,可以聯系我們。
相關主題:非關系型數據庫
更多深度文章,請關注云計算頻道:https://yq.aliyun.com/cloud
近日有 MongoDB 用戶遇到一個問題,使用 Wiredtiger 存儲引擎的 MongoDB 無法啟動,咨詢我數據能否恢復回來,能恢復多少是多少 ...
問題出現的場景據用戶描述是「mongod磁盤寫滿了,導致進程 crash」,嘗試重新啟動,結果 wiredtiger 報錯,錯誤信息類似如下,類似的問題 mongodb jira 上也有人提過,可以參考 SERVER-26924,說明此時 MongoDB 數據文件已經損壞.
2017-03-28T22:06:05.315-0500 W - [initandlisten] Detected unclean shutdown - /data/mongodb/mongod.lock is not empty.
MongoDB 3.2及以后的版本已經很少會出現這樣的問題,至少從我接觸 MongoDB 到現在還沒實際遇到過這個問題,不過既然問題已經發生,我們來看看遇到這種情況應該怎么恢復數據?
如何恢復 MongoDB 數據?
第一招: 從復制集其他節點同步數據
MongoDB 通過復制集能保證高可靠的數據存儲,通常生產環境建議使用「3節點復制集」,這樣即使其中一個節點崩潰了無法啟動,我們可以直接將其數據清掉,重新啟動后,以全新的 Secondary 節點加入復制集,它會自動的同步數據,這樣也就達到了恢復數據的目的.
然而不幸的是,該用戶的 MongoDB 實例 只部署了一個節點 ... 我只能呵呵了 ...
第二招:從最近的一個備份集恢復數據
有的時候可能出現一些極端的case,比如遇到自然災害,復制集所有節點都掛了(或者像上面的用戶這樣,你的復制集只部署一個節點...),這時第一招就沒法用了.
此時,如果靠譜的你剛好對數據做了備份,此時就排上用場了,比如你每天對 MongoDB 做一次全量備份,那么你就可以把數據恢復到最近一天的數據了;如果你更靠譜的還對數據做了增量本分,能恢復的數據就更多了.
但是可想而知,這個用戶既然能部署一個「只有單個節點的復制集」,肯定也不會想到去對數據庫進行備份了 ...
第三招: repair 模式啟動 MongoDB
當 MongoDB 無法啟動時,通常是因為數據文件出現了不一致,mongod 支持以 repair 的模式啟動,mongod 會盡可能的嘗試自己去修復數據的不一致狀態,修復過程中盡可能多的保留有效的數據.
但 repair 也不是對所有的場景都有效,repair 會先加載 MongoDB 所有的集合信息,然后針對每個集合來 repair,如果存儲元數據的數據文件損壞,repair 也是沒法工作的.
mongod --repair // 用戶嘗試按這種方式啟動,仍然報相同的錯誤
第四招:使用 wireditger 工具恢復
以上3招都不行,我的第一想法就是通過 wiredtiger 的 salvage 功能去盡可能的恢復數據(salvage 可翻譯為數據打撈,即針對一個wt的數據文件,盡可能多的從中提取有效的數據),本來是想寫個工具來做這個事情.不過調研了一下發現
1. repair 模式啟動,實現時也是調用的 wiredtiger 的 salvage 接口實現. 2. wireditger 自帶的一個命令行工具 wt,包含了 salvage 的功能. 3. 找到一篇使用 wt 工具恢復 MongoDB 數據的文章,寫的非常贊.
網友總結的使用 wiredtiger 工具 wt 恢復數據的方法原理很簡單,就是通過恢復 wiredtiger 數據文件來恢復MongoDB數據,我實驗了一下,的確可行,而且原文的步驟介紹已經非常詳細,這里就不再贅述.需要注意的是
MongoDB 3.2 最新版本已經是了 wiredtiger 2.8,所以編譯 wt 工具時,可以下載 2.8 版本的 wiredtiger 源代碼.
MongoDB 默認會對集合數據進行 snappy 壓縮,所以一定要確保 snappy 正確安裝,在執行 wt 工具時,通過擴展的形式加載 snappy lib,否則運行時會報錯.
如果需要恢復的集合很多,本文的方法效率是很低的.
第五招:從文件里提取bson文檔來恢復
MongoDB json格式的文檔,最終是以 BSON (Binary json) 格式持久化存儲.
假設我們有個工具叫 bsonextract
(有興趣的同學可以嘗試實現下貢獻到社區里,直接調 BSON 的接口,實現起來不難),它能從一個數據文件里分析并提取出所有 BSON 格式的內容,那么我們也就達到了恢復數據的目的.
分析時,一段數據滿足2個條件,我們即可認為是一個合法的 MongoDB 文檔
這段數據是一個合法的 BSON 文檔
包含一個 id 字段 (oplog 集合不包含 id 字段,但通常也沒有去恢復 oplog 的必要)
上面這個方法不僅只能恢復 wiredtiger 的數據,對 MongoDB 所有存儲引擎都有效.
總結
最后,issue SERVER-19815 里介紹了 MongoDB 一直在優化 MongoDB ,讓它能在 repair 模式里自動處理各種數據文件損壞(或部分丟失)的場景,目標就是萬一遇到數據集損壞的場景,repair都能自動修復掉.
下面是 repair 以后能自動處理的一些場景及處理方法
Database files missing
An entry for a file will exist in the catalogue, but on disk file is gone
Will be impossible to recover from, remove the entry from the catalogue
Warn the user strongly about this (Error message)
Database files corrupted
An entry for a file will exist in the catalogue, but on disk file is unable to be opened
Attempt to rename the collection with WiredTiger to a new table that has some mention of it being corrupted in the name
Re-create the same collection with the same name (in order to continue repair)
Warn the user strongly about this problem, the creation of the new collection
Index files missing
An entry will exist in the catalogue, but on disk file is gone
Build the index as part of repair
Index files corrupted
An entry will exist in the catalogue, but on disk file is unable to be opened
Drop, then rebuild the index as part of repair
MongoDB catalogue metadata may be out of alignment with the WT files on disk
When something is missing on disk, then this should be resolved by the changes above
When something is missing from the catalogue metadata but exists as a wt table on disk we have no recourse. We would need a user accessible function to import
If the WiredTiger metadata is corrupt, then the database is corrupt
歡迎參與《MongoDB無法啟動,如何恢復數據?》討論,分享您的想法,維易PHP學院為您提供專業教程。