MongoDB 无法启动,WiredTiger 如何恢复数据(二)?

本文涉及的产品
云原生多模数据库 Lindorm,多引擎 多规格 0-4节点
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
云数据库 MongoDB,通用型 2核4GB
简介:

2000元阿里云代金券免费领取,2核4G云服务器仅664元/3年,新老用户都有优惠,立即抢购>>>


阿里云采购季(云主机223元/3年)活动入口:请点击进入>>>,


阿里云学生服务器(9.5元/月)购买入口:请点击进入>>>,

之前写过一篇MongoDB 无法启动,如何恢复数据的文章,介绍了几种从无法启动的 MongoDB 节点恢复数据的方法,主要包括:

  1. 如果配置了副本集多节点,则从其他节点恢复(强烈建议重要的数据至少要存2份)
  2. 从最近的备份集恢复,一般重要的生产数据,需要对数据进行持续的全量/增量备份
  3. repair 模式恢复,如果元数据本身有问题,repair 模式也是无法工作的;
  4. 通过 WiredTiger 自带工具分析,对元数据损坏的情况也使用,能尽可能多的恢复数据。
  5. 通过分析 BSON 数据来提取恢复数据,但这个只对没有压缩的 mmapv1 引擎有效,默认 WiredTiger 会开启 snappy 压缩,无法通过分析 BSON 来提取出数据。

其中方法1-3比较简单,第4种方法对 WiredTiger 引擎的原理不了解,可能完全无从下手,本文将详细介绍如何通过 WiredTiger 的工具来提取有效数据。

背景知识

  1. 每个 MongoDB 的集合/索引都对应一个 WiredTiger Table; 集合名跟 Table 名的映射关系保存在元数据里,只有通过这部分元数据,才能获得这个映射关系。

    • 集合的数据对应 collecton-uniqueid-hash.wt 文件
    • 索引的数据对应 index-uniqueid-hash.wt
  2. MongoDB 所有集合的元数据,都存在一个特殊的 WiredTiger Table 里,名字叫 _mdb_catalog;这里可以看出,MongoDB 的元数据,对 WiredTiger 来说其实也只是普通数据。
  3. 只要单个表的数据有效,通过 WiredTiger 的 wt工具可以将其提取出来。默认 MongoDB 的源码里不会编译出 wt 工具,可以自行下载 WiredTiger 源码编译,接下来的介绍假设你已经编译出了 wt 工具。

恢复单个集合

假设你的数据库只有很少的集合,根据集合的大小,你可能很容易判断出集合名跟 WiredTiger 文件名的对应关系,比如

  somedb.collection ===>  somedb/collection-10--6822964274931136278 (如果没有指定 directoryPerDB 的选项,则没有 somedb/前缀
  

只要这个这个集合的数据还是完整的,没有被损坏,我们就可以通过如下步骤来恢复

Step1: 通过 wt 工具将集合数据 dump 到文件

 ./wt -v -h some_db_home -C "extensions=[./ext/compressors/snappy/.libs/libwiredtiger_snappy.so]"  -R dump -f collection.dump  somedb/collection-10--6822964274931136278 

此时,这个集合的数据就已经导出到 collection.dump 文件了,如果这一步出错,说明这个文件 WiredTiger 已经无法解析了,则无法恢复了。

Step2: 在新的实例上创建一个临时集合

 mkdir some_dest_db_home
 mongod --dbpath some_dest_db_home --port some_port
 mongo --port some_port
 > use somedb
 > db.createCollection("collection")  // 创建临时集合
 > db.collection.stats().uri // 查看该集合对应的 WiredTiger 表名

假设临时集合创建后,其在新的临时实例上集合名与 WiredTiger 表名对应关系如下

somedb.collection ===> somedb/collection-2--6822964274931136278 (如果没有指定 directoryPerDB 的选项,则没有 somedb/前缀

Step3: 将 dump 出的数据 load 到临时集合

停掉临时实例,然后将 Step1 里 dump 的数据 load 到临时集合

./wt -v -h some_dest_db_home -C "extensions=[./ext/compressors/snappy/.libs/libwiredtiger_snappy.so]" -R load -f  collection.dump -r somedb/collection-2--6822964274931136278

这时在目标实例上,访问 somedb.collection 时,访问的数据就是从「已经损坏的源实例」上 somedb.collection 的数据,只不过这个实例的 id 索引、统计元数据等是无法匹配的,但这并不影响全表扫描的数据访问。

Step4:mongodump/mongorestore 临时集合,修正数据统计信息、索引信息

通过 mongodump 从目标实例将 somedb.collection 备份出来,mongodump 只会触发对集合数据的顺序访问。

然后通过 mongorestore 重新导入,restore 后的数据即为恢复的目标数据。

恢复大量集合

上面介绍了如何恢复单个集合,如果损坏的 MongoDB 里有大量的集合,一个个按上面的流程恢复要搞到猴年马月了;要想自动化,需要解决的关键问题就是如果确定 MongoDB 集合名 与 WiredTiger 表名的映射关系,这里只需要稍加修改 MongoDB 源码,可以让 损坏的mongod 在 repair 模式下把映射关系输出

diff --git a/src/mongo/db/storage/kv/kv_database_catalog_entry.cpp b/src/mongo/db/storage/kv/kv_database_catalog_entry.cpp
index 91afa40026..523cb1fa95 100644
--- a/src/mongo/db/storage/kv/kv_database_catalog_entry.cpp
+++ b/src/mongo/db/storage/kv/kv_database_catalog_entry.cpp
@@ -260,6 +260,8 @@ void KVDatabaseCatalogEntry::initCollection(OperationContext* opCtx,

     const std::string ident = _engine->getCatalog()->getCollectionIdent(ns);

+    log() << "metadata mapping " << ns << " " << ident;
+
     RecordStore* rs;
     if (forRepair) {
         // Using a NULL rs since we don't want to open this record store before it has been

Step1: 获取损坏实例的MongoDB 集合名 与 WiredTiger 表名的映射关系,例如

somedb.collection1   collection-2--4775156767705741267
somedb.collection2   collection-4--4775156767705741267
.... 

Step2:根据上述映射关系,将集合数据逐个 dump

写个 shell 脚本很容易做到自动化,导出的文件名可以跟集合名保持一致,用于区分

Step3:创建目标实例,并预先创建好所有的集合

写个 js 脚本,通过 mongo shell 批量创建

Step4: 获取目标实例的MongoDB 集合名 与 WiredTiger 表名的映射关系,例如

somedb.collection1   collection-6--4335156767705741253
somedb.collection2   collection-8--4335156767705741253
.... 

Step5:将 dump 数据逐个 load 到 目标实例

跟 Step2 类似,需要写个 shell 脚本

Step6: 对整个目标实例(或部分 DB)进行 mongodump/mongorestore

修正 id 索引、统计信息等

祝你成功 ^_^ ^_^ ^_^

相关实践学习
MongoDB数据库入门
MongoDB数据库入门实验。
快速掌握 MongoDB 数据库
本课程主要讲解MongoDB数据库的基本知识,包括MongoDB数据库的安装、配置、服务的启动、数据的CRUD操作函数使用、MongoDB索引的使用(唯一索引、地理索引、过期索引、全文索引等)、MapReduce操作实现、用户管理、Java对MongoDB的操作支持(基于2.x驱动与3.x驱动的完全讲解)。 通过学习此课程,读者将具备MongoDB数据库的开发能力,并且能够使用MongoDB进行项目开发。 &nbsp; 相关的阿里云产品:云数据库 MongoDB版 云数据库MongoDB版支持ReplicaSet和Sharding两种部署架构,具备安全审计,时间点备份等多项企业能力。在互联网、物联网、游戏、金融等领域被广泛采用。 云数据库MongoDB版(ApsaraDB for MongoDB)完全兼容MongoDB协议,基于飞天分布式系统和高可靠存储引擎,提供多节点高可用架构、弹性扩容、容灾、备份回滚、性能优化等解决方案。 产品详情: https://www.aliyun.com/product/mongodb
相关文章
|
NoSQL MongoDB
MongoDB因服务器异常断电,无法启动异常的修复
本文是博主遇到MongoDB启动异常的解决方法记录,希望对大家有所帮助。
1222 0
|
存储 NoSQL
MongoDB无法启动,如何恢复数据?
近日有 MongoDB 用户遇到一个问题,使用 Wiredtiger 存储引擎的 MongoDB 无法启动,咨询我数据能否恢复回来,能恢复多少是多少 ... 问题出现的场景据用户描述是「mongod磁盘写满了,导致进程 crash」,尝试重新启动,结果 wiredtiger 报错,错误信息类似如下,类似的问题 mongodb jira 上也有人提过,可以参考 SERVER-26924,说明此时 MongoDB 数据文件已经损坏。
|
NoSQL MongoDB
MongoDB服务无法启动,发生服务特定错误:100
问题:MongoDB服务无法启动,发生服务特定错误:100 原因:没有正常关闭mongod服务,导致mongod被锁 解决方案:进入db文件夹,删除mongod.
2233 0
|
存储 NoSQL
MongoDB 存储引擎 WiredTiger 原理解析
在团队内部分享了 Wiredtiger 引擎的原理,为此画了多张图来辅助说明,对了解 Wiredtiger 应该是非常有帮助的,内容分享出来给大家。暂时没时间整理文字版,对实现原理非常感兴趣的同学,如果PPT没讲明白,可以找我私下交流。
|
NoSQL Shell 数据库
mongoDB因root启动关闭数据库导致mongo普通用户无法启动
??最近,使用mongoDB数据库时,偶然使用了root启停数据库,导致后来mongo用户无法启动数据库,报权限拒绝,但是root可以正常启停mongoDB数据库。
1671 0

相关产品

  • 云数据库 MongoDB 版
  • http://www.vxiaotou.com