Wiredtiger工具恢復MongoDB數據


前幾日在VPS折騰MongoDB,由於機器內存實在是太小了(1G,又跑了別的程序),進行重建索引操作時,內存不足被系統給kill了。強制kill的Mongo無法在repair模式下恢復,只能直接用Wiredtiger工具讀取二進制數據文件進行恢復了。

准備

官方文檔對於這種情況並沒有給予更多的提示了,這個時候只能拿出強大的Google了(百度已經拯救不了)。
經過一番資料查找,得出以下結論:

  • repair模式失敗的情況下,恢復MongoDB是比較困難了
  • MongoDB的數據使用WiredTiger引擎進行存儲,可以直接使用相關工具讀取二進制文件數據
  • 網上有一篇成功恢復數據的文章可以參考 Link

按照資料,首先要找到你需要恢復的Collection所對應的wt文件,它們一般在Mongo安裝目錄的data文件夾下面,文件的格式應該類似這樣

collection-0--282010455938071573.wt

  然后把數據文件和data下面其他一些存有必要信息的文件一起復制到一個新的目錄mongo-bak(為啥不在原來目錄操作?又失敗了怎么辦),如下:

collection-0--282010455938071573.wt
_mdb_catalog.wt
sizeStorer.wt
storage.bson
WiredTiger
WiredTiger.basecfg
WiredTiger.lock
WiredTiger.turtle
WiredTiger.wt

  數據准備就緒,我們需要一個工具 wt utility,

wget http://source.wiredtiger.com/releases/wiredtiger-3.0.0.tar.bz2
tar xvf wiredtiger-3.0.0.tar.bz2
cd wiredtiger-3.0.0
sudo yum install snappy-devel -y
./configure --enable-snappy
make

  

注意:我的系統是CentOS,如果你是Ubuntu的話,要把上面命令中的
sudo yum install snappy-devel -y
換成
sudo apt-get install libsnappy-dev build-essential

snappy是必須要安裝的插件,不然無法正常解碼二進制數據問題(就算你使用zlib模式進行壓縮,還是需要它)

打撈數據

裝好工具后,執行

./wt -v -h ../mongo-bak -C "extensions=[./ext/compressors/snappy/.libs/libwiredtiger_snappy.so]" -R salvage collection-14--4826876641079835696.wt

其中../mongo-bak是我們剛剛放恢復文件的目錄,把損壞的data文件拷貝到../mongo-bak這里面,全部考進來,collection-0--282010455938071573.wt就是需要恢復的wt文件

順利的話,可以看到這樣的信息  /mnt/mongodb/data 是mongodb里的data 文件的路徑

WT_SESSION.salvage 77982300

  

里面的數字應該是可以恢復的記錄,有時候你會發現這個數字比預想的要大,原因是mongo把刪除操作也會緩存在內存中,意外關閉時來不及寫入磁盤,導致數據量增多。

另外,剛剛那個操作會重寫wt文件里面的內容,所以盡量不要用源文件進行操作。修復好的wt文件並不能被mongo直接使用,我們需要使用wt工具里面的dump命令把里面的數據進行導出, 輸入以下命令:

./wt -v -h ../mongo-bak -C "extensions=[./ext/compressors/snappy/.libs/libwiredtiger_snappy.so]" -R dump -f ../collection.dump collection-0--282010455938071573

  這個命令會跑比較長的時間,可以用另一個命令行窗口查看collection.dump文件的生成情況,值得注意的事,根據集合內容的不同,dump文件的大小也有比較大的差異,我的一個3G大小zlib模式的wt文件,輸出的dump有27G大小,一定要准備充足的磁盤空間,另外內存大概也會占用和wt文件近似的大小。

重建數據

原來的Mongo已經不可用了,我們需要一個新的Mongo來承載恢復出來的數據,首先在新的Mongo中建立一個collection

use cloud
db.historydatas.insert({test: 1})
db.historydatas.remove({})
db.historydatas.stats()

  這里在cloud數據庫下建立了historydatas集合,stats命令為了查看這個集合對應的wt文件,在輸出的信息里,能找到這樣一行

"uri" : "statistics:table:collection-7895--1435676552983097781"

  

其中的collection-7895--1435676552983097781就是wt文件的名字了

先把新的mongo停了,我們需要直接對數據文件進行操作

 

./wt -v -h /mnt/mongodb/data -C "extensions=[./ext/compressors/snappy/.libs/libwiredtiger_snappy.so]" -R load -f ../collection.dump -r collection-5--9115211387822471702

  這里的/mnt/mongodb/data是新mongo的存放數據文件的地址,wt工具會把dump直接寫入對應的集合文件里,完成后會看到

table:collection-7895--1435676552983097781: 77982300

  好了,我們再次啟動mongo

root> show dbs
historydatas → 3.087GB
local → 0.000GB
root> use anydb
switched to db historydatas
historydatas> show collections
back → 0.000GB / 3.087GB
historydatas> db.back.count()
0

  詭異的事情出現了,數據庫大小看起來是沒有問題的,但查不到記錄總數

historydatas> db.back.find({}, {_id: 1})
{
  "_id": ObjectId("55e07f3b2e967329c888ac74")
}
{
  "_id": ObjectId("55e07f3b2e967329c888ac76")
}
...
{
  "_id": ObjectId("55e07f402e967329c888ac85")
}
Fetched 20 record(s) in 29ms -- More[true]

  可見數據已經寫入了,但數據庫的狀態還是有點問題的,我們直接執行

db.repairDatabase()

  進行修復,然后就可以正常查看記錄總數了

historydatas> db.back.count()
7789230

  太好了,現在數據恢復了,但里面的內容肯定有不同程度的缺失,需要進一步的處理。

其他

根據網上的資料,本文中的操作僅對 >=3.2版本的mongo有效。

正確mongo流程可以按照官網提示,使用 --repair 命令進入修復模式,mongo會對所有數據進行一次掃描,並且重建索引,等到修復完畢就可以正常啟動了。
但這個操作是有一個前提的,那就是文件數據必須要完整。問題是我的Mongo是被強制kill的,文件數據難免已經混亂,所以每次修復程序在重建索引這一步都會報錯。

***wiredtiger 項目github地址,一定要選擇對應的mongodb版本下載***

https://github.com/wiredtiger/wiredtiger

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM