zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    MT【280】最小值函数
    MT【279】分母为根式的两个函数
    MT【278】二次齐次化
    selenium之 chromedriver与chrome版本映射表
    django使用数据库锁
    mysql添加行内锁
    Django 通过url 获取url名称
    Django Q的其他用法
    Django 的 QueryDict
    Django 获取带参数的url
  • 原文地址:https://www.cnblogs.com/adjk/p/13303802.html
Copyright © 2011-2022 走看看