Wiredtiger工具恢复MongoDB数据
<p>前几日在VPS折腾MongoDB,由于机器内存实在是太小了(1G,又跑了别的程序),进行重建索引操作时,内存不足被系统给kill了。强制kill的Mongo无法在<code>repair</code>模式下恢复,只能直接用Wiredtiger工具读取二进制数据文件进行恢复了。</p><h2 id="准备">准备</h2>
<p>官方文档对于这种情况并没有给予更多的提示了,这个时候只能拿出强大的Google了(百度已经拯救不了)。<br>经过一番资料查找,得出以下结论:</p>
<ul>
<li>在<code>repair</code>模式失败的情况下,恢复MongoDB是比较困难了</li>
<li>MongoDB的数据使用WiredTiger引擎进行存储,可以直接使用相关工具读取二进制文件数据</li>
<li>网上有一篇成功恢复数据的文章可以参考 Link</li>
</ul>
<p>按照资料,首先要找到你需要恢复的Collection所对应的<code>wt</code>文件,它们一般在Mongo安装目录的<code>data</code>文件夹下面,文件的格式应该类似这样</p>
<div class="cnblogs_Highlighter">
<pre class="brush:java;gutter:true;">collection-0--282010455938071573.wt
</pre>
</div>
<p> 然后把数据文件和<code>data</code>下面其他一些存有必要信息的文件一起复制到一个新的目录<code>mongo-bak</code>(为啥不在原来目录操作?又失败了怎么办),如下:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:java;gutter:true;">collection-0--282010455938071573.wt
_mdb_catalog.wt
sizeStorer.wt
storage.bson
WiredTiger
WiredTiger.basecfg
WiredTiger.lock
WiredTiger.turtle
WiredTiger.wt
</pre>
</div>
<p> 数据准备就绪,我们需要一个工具 wt utility,</p>
<div class="cnblogs_Highlighter">
<pre class="brush:java;gutter:true;">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
</pre>
</div>
<p> </p>
<p>注意:我的系统是CentOS,如果你是Ubuntu的话,要把上面命令中的<br><code>sudo yum install snappy-devel -y</code><br>换成<br><code>sudo apt-get install libsnappy-dev build-essential</code></p>
<p>snappy是必须要安装的插件,不然无法正常解码二进制数据问题(就算你使用zlib模式进行压缩,还是需要它)</p>
<h2 id="打捞数据">打捞数据</h2>
<p>装好工具后,执行</p>
<div class="cnblogs_Highlighter">
<pre class="brush:java;gutter:true;">./wt -v -h ../mongo-bak -C "extensions=[./ext/compressors/snappy/.libs/libwiredtiger_snappy.so]" -R salvage collection-14--4826876641079835696.wt
</pre>
</div>
<p>其中<code>../mongo-bak</code>是我们刚刚放恢复文件的目录,把损坏的data文件拷贝到../mongo-bak这里面,全部考进来,<code>collection-0--282010455938071573.wt</code>就是需要恢复的wt文件</p>
<p>顺利的话,可以看到这样的信息 /mnt/mongodb/data 是mongodb里的data 文件的路径</p>
<div class="cnblogs_Highlighter">
<pre class="brush:java;gutter:true;">WT_SESSION.salvage 77982300
</pre>
</div>
<p> </p>
<p>里面的数字应该是可以恢复的记录,有时候你会发现这个数字比预想的要大,原因是mongo把删除操作也会缓存在内存中,意外关闭时来不及写入磁盘,导致数据量增多。</p>
<p>另外,刚刚那个操作会重写wt文件里面的内容,所以尽量不要用源文件进行操作。修复好的wt文件并不能被mongo直接使用,我们需要使用wt工具里面的dump命令把里面的数据进行导出, 输入以下命令:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:java;gutter:true;">./wt -v -h ../mongo-bak -C "extensions=[./ext/compressors/snappy/.libs/libwiredtiger_snappy.so]" -R dump -f ../collection.dump collection-0--282010455938071573
</pre>
</div>
<p> 这个命令会跑比较长的时间,可以用另一个命令行窗口查看<code>collection.dump</code>文件的生成情况,值得注意的事,根据集合内容的不同,dump文件的大小也有比较大的差异,我的一个3G大小zlib模式的wt文件,输出的dump有27G大小,一定要准备充足的磁盘空间,另外内存大概也会占用和wt文件近似的大小。</p>
<h2 id="重建数据">重建数据</h2>
<p>原来的Mongo已经不可用了,我们需要一个新的Mongo来承载恢复出来的数据,首先在新的Mongo中建立一个collection</p>
<div class="cnblogs_Highlighter">
<pre class="brush:java;gutter:true;">use cloud
db.historydatas.insert({test: 1})
db.historydatas.remove({})
db.historydatas.stats()
</pre>
</div>
<p> 这里在cloud数据库下建立了historydatas集合,stats命令为了查看这个集合对应的wt文件,在输出的信息里,能找到这样一行</p>
<div class="cnblogs_Highlighter">
<pre class="brush:java;gutter:true;">"uri" : "statistics:table:collection-7895--1435676552983097781"
</pre>
</div>
<p> </p>
<p>其中的<code>collection-7895--1435676552983097781</code>就是wt文件的名字了</p>
<p>先把新的mongo停了,我们需要直接对数据文件进行操作</p>
<p> </p>
<div class="cnblogs_Highlighter">
<pre class="brush:java;gutter:true;">./wt -v -h /mnt/mongodb/data -C "extensions=[./ext/compressors/snappy/.libs/libwiredtiger_snappy.so]" -R load -f ../collection.dump -r collection-5--9115211387822471702
</pre>
</div>
<p> 这里的/mnt/mongodb/data是新mongo的存放数据文件的地址,wt工具会把dump直接写入对应的集合文件里,完成后会看到</p>
<div class="cnblogs_Highlighter">
<pre class="brush:java;gutter:true;">table:collection-7895--1435676552983097781: 77982300
</pre>
</div>
<p> 好了,我们再次启动mongo</p>
<div class="cnblogs_Highlighter">
<pre class="brush:java;gutter:true;">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
</pre>
</div>
<p> 诡异的事情出现了,数据库大小看起来是没有问题的,但查不到记录总数</p>
<div class="cnblogs_Highlighter">
<pre class="brush:java;gutter:true;">historydatas> db.back.find({}, {_id: 1})
{
"_id": ObjectId("55e07f3b2e967329c888ac74")
}
{
"_id": ObjectId("55e07f3b2e967329c888ac76")
}
...
{
"_id": ObjectId("55e07f402e967329c888ac85")
}
Fetched 20 record(s) in 29ms -- More
</pre>
</div>
<p> 可见数据已经写入了,但数据库的状态还是有点问题的,我们直接执行</p>
<div class="cnblogs_Highlighter">
<pre class="brush:java;gutter:true;">db.repairDatabase()
</pre>
</div>
<p> 进行修复,然后就可以正常查看记录总数了</p>
<div class="cnblogs_Highlighter">
<pre class="brush:java;gutter:true;">historydatas> db.back.count()
7789230
</pre>
</div>
<p> 太好了,现在数据恢复了,但里面的内容肯定有不同程度的缺失,需要进一步的处理。</p>
<h2 id="其他">其他</h2>
<p>根据网上的资料,本文中的操作仅对 >=3.2版本的mongo有效。</p>
<p>正确mongo流程可以按照官网提示,使用 <code>--repair</code> 命令进入修复模式,mongo会对所有数据进行一次扫描,并且重建索引,等到修复完毕就可以正常启动了。<br>但这个操作是有一个前提的,那就是文件数据必须要完整。问题是我的Mongo是被强制kill的,文件数据难免已经混乱,所以每次修复程序在重建索引这一步都会报错。</p>
<p>***wiredtiger 项目github地址,一定要选择对应的mongodb版本下载***</p>
<p>https://github.com/wiredtiger/wiredtiger</p>
<p> </p><br><br>
来源:https://www.cnblogs.com/adjk/p/13303802.html
頁:
[1]