在数据库运维过程中,如果运维不规范,未建立容灾环境并未制定合适的备份策略并备份,在某些极端情况下(比如主机异常断电),可能导致数据库实例无法启动。此时,怎么尽最大的可能拯救数据?
在Oracle中,提供了一些隐含参数或者方法让数据库强制启动,并在捞出数据后重建数据库,或者利用DUL等工具尽可能的进行数据提取。那么在mongodb数据库的运维过程中,遭遇数据库文件损坏,实例无法启动的时候怎么办?我们都知道Mongodb从3.2版开始,默认使用的wiredTiger开源存储引擎,通过在github上下载wt引擎的源码,可以编译生成一个wt工具,利用该工具可以从mongodb数据文件中捞出数据。
[
数据恢复
]
工具安装
软件下载地址:https://github.com/wiredtiger/wiredtiger,安装方法:
- 安装依赖包
yum-y install snappy.x86_64 snappy-devel.x86_64
- 编译安装
./configure--enable-snappy –prefix=/usr/local/wiredTiger
make&&makeinstall
数据恢复
在mongodb数据目录的文件结构中,包括数据库文件和WiredTiger.wt等元数据文件,若元数据文件丢失,则会导致wt工具也无法恢复数据,出现类似如下报错:
[1600001107:222670][28965:0x7f7a4a987740],file:WiredTiger.wt, connection: __posix_open_file, 715:/data/mongodb/WiredTiger.wt: handle-open: open: No such file ordirectory
如上图所示,需保证红框外的文件都在,才能从数据文件中抓取数据。
wt -v -h /data/mongodb -C"extensions=[/usr/local/wiredtiger/lib/libwiredtiger_snappy.so]"list –列出所有的对象名称,由于WT引擎默认使用了snappy压缩算法,所以需要使用extensions显示指定类文件位置。
从数据文件中导出数据:
/usr/local/wiredtiger/bin/wt -v -h /data/mongodb -C"extensions=[/usr/local/wiredtiger/lib/libwiredtiger_snappy.so]" dump -f /home/mongo/a.dmp test/collection/7-6614138329248103296
导出的文件在此时不是json文件,不能直接读取,需导入一个临时数据库中
>show dbs;
admin 0.000GB
config 0.000GB
local 0.000GB
>use test
>db.createCollection("test");
{"ok" : 1 }
>show tables;
test
>db.test.stats().wiredTiger.uri;
statistics:table:test/collection/0--2648066414802528487 --获取临时集合的数据文件信息
[mongo@node1~]$ mongod -f /etc/mongodb/mongodb1.conf ---shutdown##停止临时数据库,否则在导入的时候会报资源忙
[1600004969:259849][25396:0x7f9657853740],wiredtiger_open: __posix_file_lock, 410:/data/mongodb1/WiredTiger.lock: handle-lock: fcntl: Resourcetemporarily unavailable
[1600004969:259905][25396:0x7f9657853740],wiredtiger_open: __conn_single, 1720: WiredTiger database is alreadybeing managed by another process: Device or resource busy
数据导入:
[mongo@node1~]$ /usr/local/wiredtiger/bin/wt -v -h /data/mongodb1 -C"extensions=[/usr/local/wiredtiger/lib/libwiredtiger_snappy.so]"-R load -f /home/mongo/a.dmp -rtest/collection/0--2648066414802528487
file:test/collection/0--2648066414802528487:100002 --提示导入了100002个document
启动数据库,但是我们发现此时导入的数据可以find,但是count为0,如下图:
此时,我们采用导出和导入的方法更新元数据
再次查询,集合文档数据量count可正常显示,见下图:
注:wt工具导出和导入数据只能按集合逐一进行,mongodump和mongorestore修复元数据,可以按库多个集合同时修正。
[
总结
]
本文档使用的案例是在测试环境的测试案例。本文仅仅是提供一种在极端情况下尽可能救援数据的一种方法,但使用过程中也有诸多限制。本人认为,成熟的运维应该是制定完善的运维方案,建立合适的数据库备份策略和数据库容灾架构,不到万不得已,不使用此类非常规的手段恢复数据。