环境信息
Mongodb版本:3.2.17
操作系统:centos 7.0.1406
问题表现
日志内打印 chown: cannot access '/data/db/WiredTiger.turtle':No such file or directory无法启动Mongodb
查看Mongodb数据目录,发现存在Wiretiger.turtle,ll命令查看,该文件所属用户,所属组,时间,权限信息等皆为问号
原因分析
猜测由于断电原因导致WiredTiger.turtle文件损坏,其中WireTiger为Mongodb所使用的默认存储引擎,WireTiger.wt文件为存储引擎的元数据,而WireTiger.turtle文件是WireTiger.wt文件的元数据[1][2].查阅资料未发现可直接修复该文件的办法[3],进行过测试,用 WT工具修复mongodb数据并不适用于Wiretiger.turtle文件丢失的情况[4][5][6][7].
修复思路
在mongodb,会将建立的collection信息写入数据目录下名称类似collection-14--6455635868234258390.wt的文件中,利用4.x版本的Mongodb更好的数据修复能力,将需要恢复的collection-xxx-wt文件替换4.x版本的collection-xxx-wt,运行mongodb --repair指令,进行数据恢复4,数据恢复出来后会丢失原来的库名与表名,需要自己通过恢复的内容判断原先的库名与表名
修复步骤
安装4.x版本Mongo和mongo工具
打开https://www.mongodb.com/try/download/database-tools?tck=docs_databasetools
- 下载并安装4.x版本的mongodb
- 下载并安装mongodb工具databasetools(为了使用mongodump与mongoretore工具将数据从mongodb4.x复制回我当前的3.x的mongodb)
在4.x版本Mongo中新建colleciton及插入数据,查询该collection的文件路径
此处我创建了数据库test,并创建了集合cola,并通过stat命令查询到集合的文件路径
db.cola.insert({"a":"b"});//新建colleciton及插入数据(插入时如果cola不存在,mongo会自动给创建)
db.cola.stats();//可以通过给命令查询该集合存储的文件名
如下,查询结果中wiredTiger.uri的值“statistics:table:collection-120--8692011111779330506”中的collection-120--8692011111779330506即为存储该集合cola的文件名
{
"ns" : "test.colb",
"count" : 2679549,
"size" : 2448341002,
"avgObjSize" : 913,
"storageSize" : 580358144,
"capped" : false,
"wiredTiger" : {
"metadata" : {
"formatVersion" : 1
},
"creationString" : "",
"type" : "file",
"uri" : "statistics:table:collection-120--8692011111779330506"
}
关闭4.x版本mongo,将原来的collection--xxx.wt覆盖上一步查询到的collection-xxx.wt文件
执行repair
由于我启动的mongodb以mongod运行,所以我也以mongod用户运行repair命令
su mongod -c "mongod --dbpath /var/lib/mongo --repair"
启动mongodb,查询cola,检查丢失的数据是否恢复
启动4.x版本mongodb(或者其他启动方式)
service mongod start
查询cala的数据,如果出现需要恢复的数据,并且数量没有问题,说明恢复成功
db.cola.find()
最后的处理
可以通过mongo提供的工具mongodump,mongoexport,mongoretore,mongoimport将恢复的数据从4.x版本mongodb导入到原来的旧版本数据库,至此数据恢复完成
我的处理步骤,也可以自行通过mongoexport与mongoimport配合进行恢复:
-
通过mongodump命令与mongoretore命令将数据导回到3.x的mongodb中的test库内
导出
mongodump -h 4.x数据库ip -d 需要备份的数据库名 -o 备份的路径
导入
mongorestore -h 3.x数据库ip -d 3.x数据库名 备份的数据
-
运行下述mongodb命令,将每个表恢复回原来的数据库的表内,例如下面是将表cola恢复会原来的audio库中的file表
var count=0; var ops=[]; var dbase="audio";//原来的数据库名 var col="file";//原来的表名 var colbak="cola";//数据临时存储的表名 db.colbak.find({}).forEach(function(e){ ops.push({insertOne : { "document" : e}}); count++; if(count>0&&count%1000==0) { db.getSiblingDB(dbase).col.bulkWrite(ops,{ordered:false}); ops = []; print("更新条数:" + count); } }); if(ops.length > 0){ db.getSiblingDB(dbase).col.bulkWrite(ops, {ordered:false}); } print("更新条数:" + count);
其他问题
-
是否能直接删除Wiretiger.turtle文件,再运行mongo --repair进行修复
-
答:不能,在我手上环境里的3.x和4.x版本的mongodb上测试过,无论是运行mongo --repaire,还是直接重启mongo,mongo都会新建Wiretiger.turtle,查看日志打印如下信息:
unexpected file WiredTiger.wt found, renamed to WiredTiger.wt.1
可能多次重启mongodb都无法启动,即使mongodb能启动起来,查看mongodb,看到的将是一个空的mongodb数据库
-
-
是否Mongodb 4.x版本,5.x版本可以运行mongo --repaire进行修复
- 答:还未测试过
-
运行mongo --repair 后,启动mongo提示permission denied类似的错误
- 答:可能是运行mongo --repair 与启动mongodb服务的用户不是同一个用户,可以同过ll命令查看下mongodb的数据目录下这些文件的所属用户与权限,如果不一样例如Wiredtiger.turtle文件的所属用户为root,而其他文件的所属用户为mongodb,则应该是该问题,对权限做下处理,例如运行mongo --repair命令时保持与启动mongodb的用户为同一个用户或者直接对数据目录赋予755权限
-
修复一个2g多的collection-xxx.wt文件,运行mongo --repair 后,没有打印明显修复某某数据的信息,并且很快就关闭了,启动mongo提示报错(不是permission denied类似的错误)
- 答: 我也曾经出现过这个情况,关闭mongodb数据库,把数据命令删除,把修复过程重新执行多几遍
-
能否修复索引信息
- 答:未试过,可自行尝试.