暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

使用WT工具恢复MongoDB数据

无聊程序员 2021-12-02
938
难度:中等

众所周知MongoDB的底层存储是由WiredTiger
负责的,其数据文件也是.wt
格式。既然如此,我们就有可能不通过MongoDB服务,而是直接用wt
工具从数据文件中恢复数据。虽然我们通常推荐生产环境一定要配置复制集,但是很无奈,技术社区已经数次有人因为单机运行,最后硬盘损坏等原因导致无法启动。wt
工具作为最后一根稻草,可以在放弃治疗前再尝试挽救一下。

1 编译

wt
工具可以运行于Linux和Windows上。因为各自的操作系统和MongoDB版本不同,可能产生较多的组合。在使用时应该根据自己情况编译适合的版本。下面以CentOS 7为例演示编译过程。

1.1 安装操作系统依赖

sudo yum install -y epel-release libtool automake snappy snappy-devel lz4 lz4-devel zstd zstd-devel libzstd-devel zlib zlib-devel git make vim-common

1.2 准备源码

git clone https://github.com/wiredtiger/wiredtiger.git

根据所使用的MongoDB版本,应该选择正确的wt
分支。例如我当前使用的MongoDB 4.4.1
,那么同样应该选择WiredTiger的相应tag mongodb-4.4.1

> git tag | grep 4.4.1
mongodb-4.4.1
mongodb-4.4.1-rc0
mongodb-4.4.1-rc1
mongodb-4.4.1-rc2
mongodb-4.4.1-rc3
mongodb-4.4.10
mongodb-4.4.10-rc0
mongodb-4.4.11-rc0
> git checkout tags/mongodb-4.4.1 -b v4.4.1

1.3 编译源码

sh autogen.sh
./configure --disable-shared --with-builtins=lz4,snappy,zlib,zstd
make -j $(nproc)
make install

简单起见我们使用了--disable-shared
来将动态链接库直接打包到执行文件中,这样可以避免很多后续的麻烦,代价是生成的执行文件较大。

2 读取数据

如果有幸dbpath
中的其他文件没有丢失,包括:

  • WiredTiger*

  • 要恢复的集合的collection-xxx.wt

  • 与要恢复集合相关的index文件

则可以直接使用wt工具恢复数据了:

wt dump file:collection-10--2280053313118266952.wt

不过,如果所有东西都还在的话,为什么还要用wt
来恢复呢?所以我相信大部分人到这里都是跑不下去的。所以来看下一步,当你丢到只剩个裤衩子的时候该怎么办。

3 数据恢复

wt
读取数据的基本前提条件是要有元数据,也就是WiredTiger*
那堆文件。那我们就来尝试构造这些文件:

mkdir temp
cd temp
touch WiredTiger WiredTiger.lock
wt list

为了简单起见,后续步骤我们没有使用wt
来完成,而是使用MongoDB:

mongod --dbpath ./

启动另一个窗口,使用mongo shell连接到当前实例:

mongo

任意创建一个集合,我们将把数据恢复到这个集合中:

db.dump.insert({x: 1});
db.dump.stats().wiredTiger.uri
# statistics:table:collection-7-666354062479792805

collection-7-666354062479792805.wt
即我们要使用的目标文件名。此时应:

  • 停止mongod(直接ctrl-c)

  • 使用我们要恢复的文件覆盖上述文件

cp collection-10--2280053313118266952.wt collection-7-666354062479792805.wt
  • wt
    帮我们修复文件:

wt salvage file:collection-7-666354062479792805.wt
  • 重启mongod
    进程:

mongod --dbpath ./
  • 再次使用shell连接到MongoDB,在dump
    集合中即可找到我们要恢复的数据。

注意此时集合数据虽然恢复正常,但如果你count()
就会发现返回结果是1。不用担心,这个问题很容易修复:

db.dump.validate({full: true});

下面该怎么办大家心里有数了吗?

4 后记

复制集可以说是MongoDB的标配,有复制集存在的情况下很多问题本可以避免。无论你的老板如何要求你节省成本,希望你顶住压力,把复制集上上去。

最后,希望大家的职业道路一帆风顺,永远不要有用到此文的一天。


随堂考


关于作者:

张耀星,MongoDB大中华区首席咨询顾问,供职于MongoDB售后服务团队5年+,拥有近10年MongoDB使用经验。

文章转载自无聊程序员,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论