(一)MongoDB恢复概述
对于任何数据库,如果要将数据库恢复到过去的任意时间点,否需要有过去某个时间点的全备+全备之后的重做日志。
接下来根据瑞丽航空的情况进行概述:
全备:每天晚上都会进行备份;
重做日志备份:MongoDB只有开启主从复制或者副本集时才会开启重做日志,主从复制存放在local数据库下的“oplog.$main”集合中,复制集的日志存放在local数据库下的oplog.rs集合中,该集合是一个上限集合,当达到固定大小时,最老的记录会被自动覆盖。因此需要注意,MongoDB的重做日志并不会一直保存着,能否恢复到故障点,完全取决于日志是否完整。
(二)基础环境
本次测试备份恢复使用的是MongoDB 4.2版本副本集环境,副本集配置如下:
rstest:PRIMARY> rs.config() { "_id" : rstest",version2protocolVersion" : NumberLong(1),1)">writeConcernMajorityJournalDefault" : truemembers : [ { 0host192.168.10.41:27017arbiterOnlyfalsebuildIndexeshiddenpriority3tags : { },1)">slaveDelayvotes },{ 192.168.10.42:27017 : { },1)">192.168.10.43:27017 : { },1)"> } ],1)">settings : { chainingAllowedheartbeatIntervalMillis2000heartbeatTimeoutSecs10electionTimeoutMillis10000catchUpTimeoutMillis" : -catchUpTakeoverDelayMillis30000getLastErrorModes : { },1)">getLastErrorDefaults : { wwtimeoutreplicaSetId" : ObjectId(5f32312d4911b68cdaac02a6) } } rstest:PRIMARY>
(三)确认日志保存情况
oplog是一个上限集合,当数据量达到一定大小后,MongoDB会自动清理oplog日志信息,为了保证恢复能够正常进行,需要确认日志的时间是否符合还原需求。简单来说,oplog应该保存着自上一次备份以来的所有日志。可以使用下面方法来确认最早的oplog。
方法:查看主从复制信息
在主节点查看日志信息,可以看到oplog日志大小,因为oplog是一个固定大小的集合,所以还可以看到日志的开始、结束时间、oplog的时间差等。
(四)模拟将MongoDB恢复到任意时间点
(4.1)案例一:将整个实例恢复到某个时间点
(4.1.1)故障场景描述
业务人员发现多个MongoDB数据库均存在数据错误的情况,需要将全部数据恢复到过去的某个时刻。
(4.1.2)数据恢复方法描述
只要确定了恢复时间点,就可以使用完全备份+oplog备份,将数据恢复到过去的某个时刻。
(4.1.3)恢复过程
STEP1:模拟业务正常运行,数据正常进入MongoDB数据库
use db1 db.db1test.insert({id:1,name:'a'}) db.db1test.insert({2,1)">b}) use db2 db.db2test.insert({11,1)">aa}) db.db2test.insert({22,1)">bb'})
STEP2:执行完整备份
mongodump --authenticationDatabase admin -ulijiaman -plijiaman -o /root/backup/full
STEP3:再次模拟业务正常运行,数据正常进入MongoDB数据库
最终数据如下:
STEP4:模拟数据误操作
错误执行之后的结果:
要求把所有数据库的数据恢复到STEP4之前的状态。
STEP5:停止业务,不再往数据库写数据
STEP6:备份日志。可以备份部分日志,也可以备份全部日志
mongodump --authenticationDatabase admin -ulijiaman -plijiaman -d local -c oplog.rs -o /root/backup/oplog/
STEP7:确认数据异常时间点,对oplog集合进行分析
查询结果如下,可以确认,开始对db1.db1test集合更新的时间为Timestamp(1597371835,2)
STEP8:执行完全备份的恢复
需要注意,考虑是否需要使用"--drop"选项,如果不用该选项,会保留集合中当前的数据,如果使用了drop选项,在导入集合时会先删除集合。这里使用该选项
mongorestore --authenticationDatabase admin -ulijiaman -plijiaman --port=27017 --drop /root/backup/full/
确认全量恢复的数据,已经恢复回来
STEP9:使用oplog执行增量恢复
在恢复oplog之前,需要对其格式进行处理,否则会报错
[root@node1 local]# mongorestore --authenticationDatabase admin -ulijiaman -plijiaman --port=27017 --oplogReplay --oplogLimit 1597371835:2" /root/backup/oplog/local 2020-08-14T10:44:45.120+ preparing collections to restore from 0800 dont know what to do with file "/root/backup/oplog/local/oplog.rs.bson",skipping... t know what to do with file "/root/backup/oplog/local/oplog.rs.Metadata.json",1)">0800 Failed: no oplog file to replay; make sure you run mongodump with --oplog 0800 0 document(s) restored successfully. document(s) Failed to restore.
需要把oplog.rs.Metadata.json 文件删除,把oplog.rs.bson名字改为oplog.bson
[root@node1 local]# ls oplog.rs.bson oplog.rs.Metadata.json [root@node1 local]# pwd /root/backup/oplog/local [root@node1 local]# rm -rf oplog.rs.Metadata.json [root@node1 local]# mv oplog.rs.bson oplog.bson [root@node1 local]# oplog.bson
最后执行oplog增量恢复即可
关于恢复权限,在MongoDB2.7也有相同的问题,见上一篇文档。
STEP10:确认数据恢复情况,发现数据以及恢复到了STEP4之前的状态
至此恢复结束。
(4.2)案例二:误删除某个DB,对单个DB进行恢复
通常,每个DB承载不同的业务,相互之间没有关系,如果出现故障,往往会表现在某个DB上,因此,如果出现故障,只对相应的DB进行恢复,那将减小对业务的影响。
(4.2.1)故障场景描述
假设业务运行过程中,数据库db3被人误删除了,我们需要对db3进行恢复,并且不能影响到其它的DB业务。
(4.2.2)数据恢复方法描述
可以在当前实例上进行恢复,也可以新启动一个mongod实例,用于数据恢复,我们采用新的mongod实例来恢复数据。
1.首先新启动一个mongod实例;
2.将已有的完全备份恢复到新的实例上;
3.备份oplog,只备份db3的oplog,其它数据库的不备份;
4.使用oplog将数据库恢复到删除之前;
5.检查db3数据库的数据,确认是否恢复回来;
6.如果第5步没有问题,mongodump导出db3数据库,然后倒入到生产环境中。
(4.2.3)恢复过程
use db3
db.db3test.insert({111,1)">aaa})
db.db3test.insert({222,1)">bbb333,1)">ccc444,1)">ddd555,1)">eee666,1)">fffrstest:PRIMARY> db.db3test.5f35fff809eccc387e65cd8c5f35fff809eccc387e65cd8d5f35fff909eccc387e65cd8e5f3600b309eccc387e65cd8f5f3600b309eccc387e65cd905f3600b409eccc387e65cd91 db
db3
rstest:PRIMARY> db.dropDatabase()
{
droppeddb3ok$clusterTimeclusterTime1597374734,1)">signature
hash" : BinData(0,1)">0uoicASFK0ppoNhIEuURwElt7Qk=keyId6859599294731649027)
}
},1)">operationTime)
}
rstest:PRIMARY>