(一)MongoDB恢复概述


对于任何数据库,如果要将数据库恢复到过去的任意时间点,否需要有过去某个时间点的全备+全备之后的重做日志。

接下来根据瑞丽航空的情况进行概述:

全备:每天晚上都会进行备份;

重做日志备份:MongoDB只有开启主从复制或者副本集时才会开启重做日志,主从复制存放在local数据库下的“oplog.$main”集合中,复制集的日志存放在local数据库下的oplog.rs集合中,该集合是一个上限集合,当达到固定大小时,最老的记录会被自动覆盖。因此需要注意,MongoDB的重做日志并不会一直保存着,能否恢复到故障点,完全取决于日志是否完整。

(二)基础环境

本次测试备份恢复使用的是MongoDB 4.2版本副本集环境,副本集配置如下:

rstest:PRIMARY> rs.config()
{
"_id" : "rstest",
"version" : 2,
"protocolVersion" : NumberLong(1),
"writeConcernMajorityJournalDefault" : true,
"members" : [
{
"_id" : 0,
"host" : "192.168.10.41:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 3,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 1,
"host" : "192.168.10.42:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 2,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
},
{
"_id" : 2,
"host" : "192.168.10.43:27017",
"arbiterOnly" : false,
"buildIndexes" : true,
"hidden" : false,
"priority" : 1,
"tags" : {
},
"slaveDelay" : NumberLong(0),
"votes" : 1
}
],
"settings" : {
"chainingAllowed" : true,
"heartbeatIntervalMillis" : 2000,
"heartbeatTimeoutSecs" : 10,
"electionTimeoutMillis" : 10000,
"catchUpTimeoutMillis" : -1,
"catchUpTakeoverDelayMillis" : 30000,
"getLastErrorModes" : {
},
"getLastErrorDefaults" : {
"w" : 1,
"wtimeout" : 0
},
"replicaSetId" : ObjectId("5f32312d4911b68cdaac02a6")
}
}
rstest:PRIMARY>


(三)确认日志保存情况


oplog是一个上限集合,当数据量达到一定大小后,MongoDB会自动清理oplog日志信息,为了保证恢复能够正常进行,需要确认日志的时间是否符合还原需求。简单来说,oplog应该保存着自上一次备份以来的所有日志。可以使用下面方法来确认最早的oplog。

方法:查看主从复制信息

在主节点查看日志信息,可以看到oplog日志大小,因为oplog是一个固定大小的集合,所以还可以看到日志的开始、结束时间、oplog的时间差等。

rstest:PRIMARY> db.printReplicationInfo()
configured oplog size: 1687.392822265625MB
log length start to end: 246186secs (68.39hrs)
oplog first event time: Tue Aug 11 2020 13:48:29 GMT+0800 (CST)
oplog last event time: Fri Aug 14 2020 10:11:35 GMT+0800 (CST)
now: Fri Aug 14 2020 10:11:36 GMT+0800 (CST)

(四)模拟将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({id:2,name:'b'}) use db2
db.db2test.insert({id:11,name:'aa'})
db.db2test.insert({id:22,name:'bb'})

STEP2:执行完整备份

mongodump --authenticationDatabase admin -ulijiaman -plijiaman -o /root/backup/full

STEP3:再次模拟业务正常运行,数据正常进入MongoDB数据库

use db1
db.db1test.insert({id:3,name:'c'}) use db2
db.db2test.insert({id:33,name:'cc'})

最终数据如下:

rstest:PRIMARY> use db1
switched to db db1
rstest:PRIMARY> db.db1test.find()
{ "_id" : ObjectId("5f35f4ed09eccc387e65cd86"), "id" : 1, "name" : "a" }
{ "_id" : ObjectId("5f35f4ed09eccc387e65cd87"), "id" : 2, "name" : "b" }
{ "_id" : ObjectId("5f35f57409eccc387e65cd8a"), "id" : 3, "name" : "c" } rstest:PRIMARY> use db2
switched to db db2
rstest:PRIMARY> db.db2test.find()
{ "_id" : ObjectId("5f35f4ed09eccc387e65cd88"), "id" : 11, "name" : "aa" }
{ "_id" : ObjectId("5f35f4ee09eccc387e65cd89"), "id" : 22, "name" : "bb" }
{ "_id" : ObjectId("5f35f57509eccc387e65cd8b"), "id" : 33, "name" : "cc" }

STEP4:模拟数据误操作

# db1的db1test集合id增加100
use db1
db.db1test.update({},{$inc:{"id":100}},{multi:true}) # db2的db2test集合被删除
use db2
db.db2test.drop()

错误执行之后的结果:

rstest:PRIMARY> use db1
switched to db db1
rstest:PRIMARY> db.db1test.find()
{ "_id" : ObjectId("5f35f4ed09eccc387e65cd86"), "id" : 101, "name" : "a" }
{ "_id" : ObjectId("5f35f4ed09eccc387e65cd87"), "id" : 102, "name" : "b" }
{ "_id" : ObjectId("5f35f57409eccc387e65cd8a"), "id" : 103, "name" : "c" } rstest:PRIMARY> use db2
switched to db db2
rstest:PRIMARY> db.db2test.find()
rstest:PRIMARY>

要求把所有数据库的数据恢复到STEP4之前的状态。

STEP5:停止业务,不再往数据库写数据

STEP6:备份日志。可以备份部分日志,也可以备份全部日志

mongodump --authenticationDatabase admin -ulijiaman -plijiaman -d local -c oplog.rs -o /root/backup/oplog/

STEP7:确认数据异常时间点,对oplog集合进行分析

use local

db.oplog.rs.find(
{
$and : [
{"ns" : /db1/},
{"op" : "u" }
]
}
).sort({ts:1})

查询结果如下,可以确认,开始对db1.db1test集合更新的时间为Timestamp(1597371835, 2)

/* 1 */
{
"ts" : Timestamp(1597371835, 2),
"t" : NumberLong(7),
"h" : NumberLong(0),
"v" : 2,
"op" : "u",
"ns" : "db1.db1test",
"ui" : UUID("b3566a31-f6c1-4052-82a9-90f70728c41c"),
"o2" : {
"_id" : ObjectId("5f35f4ed09eccc387e65cd86")
},
"wall" : ISODate("2020-08-14T02:23:55.576Z"),
"o" : {
"$v" : 1,
"$set" : {
"id" : 101.0
}
}
}
/* 2 */
{
"ts" : Timestamp(1597371835, 3),
"t" : NumberLong(7),
"h" : NumberLong(0),
"v" : 2,
"op" : "u",
"ns" : "db1.db1test",
"ui" : UUID("b3566a31-f6c1-4052-82a9-90f70728c41c"),
"o2" : {
"_id" : ObjectId("5f35f4ed09eccc387e65cd87")
},
"wall" : ISODate("2020-08-14T02:23:55.578Z"),
"o" : {
"$v" : 1,
"$set" : {
"id" : 102.0
}
}
}
/* 3 */
{
"ts" : Timestamp(1597371835, 4),
"t" : NumberLong(7),
"h" : NumberLong(0),
"v" : 2,
"op" : "u",
"ns" : "db1.db1test",
"ui" : UUID("b3566a31-f6c1-4052-82a9-90f70728c41c"),
"o2" : {
"_id" : ObjectId("5f35f57409eccc387e65cd8a")
},
"wall" : ISODate("2020-08-14T02:23:55.578Z"),
"o" : {
"$v" : 1,
"$set" : {
"id" : 103.0
}
}
}

STEP8:执行完全备份的恢复

需要注意,考虑是否需要使用"--drop"选项,如果不用该选项,会保留集合中当前的数据,如果使用了drop选项,在导入集合时会先删除集合。这里使用该选项

mongorestore --authenticationDatabase admin -ulijiaman -plijiaman --port=27017 --drop  /root/backup/full/

确认全量恢复的数据,已经恢复回来

rstest:PRIMARY> use db1
switched to db db1
rstest:PRIMARY> db.db1test.find()
{ "_id" : ObjectId("5f35f4ed09eccc387e65cd86"), "id" : 1, "name" : "a" }
{ "_id" : ObjectId("5f35f4ed09eccc387e65cd87"), "id" : 2, "name" : "b" }
rstest:PRIMARY> use db2
switched to db db2
rstest:PRIMARY> db.db2test.find()
{ "_id" : ObjectId("5f35f4ed09eccc387e65cd88"), "id" : 11, "name" : "aa" }
{ "_id" : ObjectId("5f35f4ee09eccc387e65cd89"), "id" : 22, "name" : "bb" }
rstest:PRIMARY>

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+0800 preparing collections to restore from
2020-08-14T10:44:45.120+0800 don't know what to do with file "/root/backup/oplog/local/oplog.rs.bson", skipping...
2020-08-14T10:44:45.120+0800 don't know what to do with file "/root/backup/oplog/local/oplog.rs.metadata.json", skipping...
2020-08-14T10:44:45.120+0800 Failed: no oplog file to replay; make sure you run mongodump with --oplog
2020-08-14T10:44:45.120+0800 0 document(s) restored successfully. 0 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]# ls
oplog.bson

最后执行oplog增量恢复即可

# 权限有问题,lijiaman用户具有root角色
mongorestore --authenticationDatabase admin -ulijiaman -plijiaman --port=27017 --oplogReplay --oplogLimit "1597371835:2" /root/backup/oplog/local # 执行成功
[root@node1 local]# mongorestore --authenticationDatabase admin -uroot2 -p123456 --port=27017 --oplogReplay --oplogLimit "1597371835:2" /root/backup/oplog/local

关于恢复权限,在MongoDB2.7也有相同的问题,见上一篇文档

STEP10:确认数据恢复情况,发现数据以及恢复到了STEP4之前的状态

rstest:PRIMARY> use db1
switched to db db1
rstest:PRIMARY> db.db1test.find()
{ "_id" : ObjectId("5f35f4ed09eccc387e65cd86"), "id" : 1, "name" : "a" }
{ "_id" : ObjectId("5f35f4ed09eccc387e65cd87"), "id" : 2, "name" : "b" }
{ "_id" : ObjectId("5f35f57409eccc387e65cd8a"), "id" : 3, "name" : "c" }
rstest:PRIMARY>
rstest:PRIMARY> use db2
switched to db db2
rstest:PRIMARY> db.db2test.find()
{ "_id" : ObjectId("5f35f4ed09eccc387e65cd88"), "id" : 11, "name" : "aa" }
{ "_id" : ObjectId("5f35f4ee09eccc387e65cd89"), "id" : 22, "name" : "bb" }
{ "_id" : ObjectId("5f35f57509eccc387e65cd8b"), "id" : 33, "name" : "cc" }
rstest:PRIMARY>

至此恢复结束。


(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)恢复过程

STEP1:模拟业务正常运行,数据正常进入MongoDB数据库

use db3
db.db3test.insert({id:111,name:'aaa'})
db.db3test.insert({id:222,name:'bbb'})
db.db3test.insert({id:333,name:'ccc'})

STEP2:执行完整备份

mongodump --authenticationDatabase admin -ulijiaman -plijiaman -o /root/backup/full

STEP3:再次模拟业务正常运行,数据正常进入MongoDB数据库

use db3
db.db3test.insert({id:444,name:'ddd'})
db.db3test.insert({id:555,name:'eee'})
db.db3test.insert({id:666,name:'fff'})

最终数据如下:

rstest:PRIMARY> db.db3test.find()
{ "_id" : ObjectId("5f35fff809eccc387e65cd8c"), "id" : 111, "name" : "aaa" }
{ "_id" : ObjectId("5f35fff809eccc387e65cd8d"), "id" : 222, "name" : "bbb" }
{ "_id" : ObjectId("5f35fff909eccc387e65cd8e"), "id" : 333, "name" : "ccc" }
{ "_id" : ObjectId("5f3600b309eccc387e65cd8f"), "id" : 444, "name" : "ddd" }
{ "_id" : ObjectId("5f3600b309eccc387e65cd90"), "id" : 555, "name" : "eee" }
{ "_id" : ObjectId("5f3600b409eccc387e65cd91"), "id" : 666, "name" : "fff" }
rstest:PRIMARY>

STEP4:模拟数据误操作

rstest:PRIMARY> db
db3
rstest:PRIMARY>
rstest:PRIMARY>
rstest:PRIMARY> db.dropDatabase()
{
"dropped" : "db3",
"ok" : 1,
"$clusterTime" : {
"clusterTime" : Timestamp(1597374734, 2),
"signature" : {
"hash" : BinData(0,"0uoicASFK0ppoNhIEuURwElt7Qk="),
"keyId" : NumberLong("6859599294731649027")
}
},
"operationTime" : Timestamp(1597374734, 2)
}
rstest:PRIMARY>

接下来执行恢复操作。

STEP5:在发现误操作之后,首先应该备份oplog,这里只涉及到db3数据库,只要备份db3的oplog即可,这样可以加快备份恢复速度

mongodump --authenticationDatabase admin -ulijiaman -plijiaman -d local -c oplog.rs -q '{"ns":{"$regex":"db3"}}'  -o /root/backup/oplog/

STEP6:先执行完全恢复

mongorestore --authenticationDatabase admin -ulijiaman -plijiaman  --port=27017 -d db3 /root/backup/full/db3

执行恢复后,db3数据已经恢复到了全备时的状态

rstest:PRIMARY> show dbs
admin 0.000GB
config 0.000GB
db1 0.000GB
db2 0.000GB
db3 0.000GB
lijiamandb 0.000GB
local 0.002GB
maxiangqian 0.000GB
rstest:PRIMARY>
rstest:PRIMARY> use db3
switched to db db3
rstest:PRIMARY> show collections
db3test
rstest:PRIMARY> db.db3test.find()
{ "_id" : ObjectId("5f35fff809eccc387e65cd8c"), "id" : 111, "name" : "aaa" }
{ "_id" : ObjectId("5f35fff809eccc387e65cd8d"), "id" : 222, "name" : "bbb" }
{ "_id" : ObjectId("5f35fff909eccc387e65cd8e"), "id" : 333, "name" : "ccc" }

STEP7:使用oplog恢复到drop操作之前

先确认drop db3数据库的时间点:Timestamp(1597374734, 2)

use local
db.oplog.rs.find(
{
$and : [
{"ns" : {"$regex":"db3"}},
{"op" : "c"},
{"o" : {"dropDatabase":1}}
]
}
).sort({ts:1})

结果如下

/* 1 */
{
"ts" : Timestamp(1597374734, 2),
"t" : NumberLong(7),
"h" : NumberLong(0),
"v" : 2,
"op" : "c",
"ns" : "db3.$cmd",
"wall" : ISODate("2020-08-14T03:12:14.206Z"),
"o" : {
"dropDatabase" : 1
}
}

执行增量恢复:

# 先处理oplog,删除文件oplog.rs.metadata.json,修改oplog.rs.bson为oplog.bson
[root@node1 local]# pwd
/root/backup/oplog/local
[root@node1 local]# ls
oplog.rs.bson oplog.rs.metadata.json
[root@node1 local]# rm -rf oplog.rs.metadata.json
[root@node1 local]# mv oplog.rs.bson oplog.bson
[root@node1 local]# ls
oplog.bson # 执行恢复
mongorestore --authenticationDatabase admin -ulijiaman -plijiaman --port=27017 --oplogReplay --oplogLimit "1597374734:1" /root/backup/oplog/local

特别注意:这里发现,oplogLimit参数,在MongoDB 2.7版本中不包含后面的时间点,在4.2里面包含后面的时间点。如果我使用时间Timestamp(1597374734, 2)来作为恢复点,则发现数据库恢复完成又被删除了。

检查数据是否已经恢复,可以确认,数据已经恢复回来

rstest:PRIMARY> db.db3test.find()
{ "_id" : ObjectId("5f35fff809eccc387e65cd8c"), "id" : 111, "name" : "aaa" }
{ "_id" : ObjectId("5f35fff809eccc387e65cd8d"), "id" : 222, "name" : "bbb" }
{ "_id" : ObjectId("5f35fff909eccc387e65cd8e"), "id" : 333, "name" : "ccc" }
{ "_id" : ObjectId("5f3600b309eccc387e65cd8f"), "id" : 444, "name" : "ddd" }
{ "_id" : ObjectId("5f3600b309eccc387e65cd90"), "id" : 555, "name" : "eee" }
{ "_id" : ObjectId("5f3600b409eccc387e65cd91"), "id" : 666, "name" : "fff" }

(4.3)案例三:误操作某个集合,对单个集合进行恢复

(4.3.1)故障场景描述

业务人员执行误删操DBA对数据进行恢复,详细过程如下:

T1~T2:业务正常运行,数据正常进入数据库

T2:使用mongodump执行数据库完全备份

T2~T4:业务正常运行,数据正常进入数据库

T4:用户误删除数据

T4~T6:业务还在运行,但是已经出现问题,如此时还能正常插入数据,但是查询、更新、删除数据存在找不到数据的错误

T6:DBA介入数据恢复

(4.3.2)数据恢复方法描述

可以在当前实例上进行恢复,也可以新启动一个mongod实例,用于数据恢复,我们在上一个例子中已经使用新建mongod实例的方式来恢复数据,本次实验我们直接在生产实例上进行恢复。

1.执行完全恢复,使用完全备份,将数据库恢复到T2时刻;

2.找到T4时刻故障之前的时间,从而确定T2~T4之间的oplog日志。结合T2时刻的全备+ T2~T4之间的oplog日志,实现数据恢复;(备注:这里不需要去确认T2之后的日志开始时间,在使用oplog恢复数据时,是通过唯一编号“_id”来操作数据的,oplog可能从全备份之前的任意时间开始,但是并不影响数据的正确性)。

3.找到T4时刻故障之后的时间,备份oplog。

4.使用oplog,实现T4~T6时间段的恢复。

(4.3.3)恢复过程

STEP1:模拟业务正常运行,数据正常进入MongoDB数据库

use db4
db.db4test.insert({id:1111,name:'aaaa'})
db.db4test.insert({id:2222,name:'bbbb'})
db.db4test.insert({id:3333,name:'cccc'})

STEP2:执行完整备份

mongodump --authenticationDatabase admin -ulijiaman -plijiaman -o /root/backup/full

STEP3:再次模拟业务正常运行,数据正常进入MongoDB数据库

use db4
db.db4test.insert({id:4444,name:'dddd'})
db.db4test.insert({id:5555,name:'eeee'})
db.db4test.insert({id:6666,name:'ffff'})

最终数据如下:

rstest:PRIMARY> db.db4test.find()
{ "_id" : ObjectId("5f36267a09eccc387e65cd92"), "id" : 1111, "name" : "aaaa" }
{ "_id" : ObjectId("5f36267a09eccc387e65cd93"), "id" : 2222, "name" : "bbbb" }
{ "_id" : ObjectId("5f36267b09eccc387e65cd94"), "id" : 3333, "name" : "cccc" }
{ "_id" : ObjectId("5f3628c809eccc387e65cd95"), "id" : 4444, "name" : "dddd" }
{ "_id" : ObjectId("5f3628c809eccc387e65cd96"), "id" : 5555, "name" : "eeee" }
{ "_id" : ObjectId("5f3628c909eccc387e65cd97"), "id" : 6666, "name" : "ffff" }
rstest:PRIMARY>

STEP4:模拟数据误操作,删除2条数据

rstest:PRIMARY> db.db4test.remove({id:{$gt:4444}})
WriteResult({ "nRemoved" : 2 }) rstest:PRIMARY> db.db4test.find()
{ "_id" : ObjectId("5f36267a09eccc387e65cd92"), "id" : 1111, "name" : "aaaa" }
{ "_id" : ObjectId("5f36267a09eccc387e65cd93"), "id" : 2222, "name" : "bbbb" }
{ "_id" : ObjectId("5f36267b09eccc387e65cd94"), "id" : 3333, "name" : "cccc" }
{ "_id" : ObjectId("5f3628c809eccc387e65cd95"), "id" : 4444, "name" : "dddd" }

STEP5:再次模拟业务正常运行,数据正常进入MongoDB数据库

use db4
db.db4test.insert({id:7777,name:'gggg'})
db.db4test.insert({id:8888,name:'hhhh'})
db.db4test.insert({id:9999,name:'kkkk'})

最终数据如下:

rstest:PRIMARY> db.db4test.find()
{ "_id" : ObjectId("5f36267a09eccc387e65cd92"), "id" : 1111, "name" : "aaaa" }
{ "_id" : ObjectId("5f36267a09eccc387e65cd93"), "id" : 2222, "name" : "bbbb" }
{ "_id" : ObjectId("5f36267b09eccc387e65cd94"), "id" : 3333, "name" : "cccc" }
{ "_id" : ObjectId("5f3628c809eccc387e65cd95"), "id" : 4444, "name" : "dddd" }
{ "_id" : ObjectId("5f3639a009eccc387e65cd98"), "id" : 7777, "name" : "gggg" }
{ "_id" : ObjectId("5f3639a009eccc387e65cd99"), "id" : 8888, "name" : "hhhh" }
{ "_id" : ObjectId("5f3639a109eccc387e65cd9a"), "id" : 9999, "name" : "kkkk" }

此时,我们发现id为5555和6666的数据是被误删除的,需要恢复回来,并且要保留执行删除命令之后的数据。

STEP6:在发现误操作之后,首先应该备份oplog,这里只涉及到db4.db4test集合,只要备份该集合的oplog即可,这样可以加快备份恢复速度

mongodump --authenticationDatabase admin -ulijiaman -plijiaman -d local -c 'oplog.rs' -q '{"ns":"db4.db4test"}'  -o /root/backup/oplog/

STEP7:对该集合执行完全恢复操作

mongorestore --authenticationDatabase admin -ulijiaman -plijiaman --port=27017 -d db4 -c db4test  /root/backup/full/db4/db4test.bson

STEP8:使用oplog,对该集合执行增量恢复操作

先查看对db4.db4test集合执行删除的开始时间Timestamp(1597389188, 1)

use local
db.oplog.rs.find(
{
$and : [
{"ns" : /db4.db4test/},
{"op" : "d" }
]
}
).sort({ts:1}) /* 1 */
{
"ts" : Timestamp(1597389188, 1),
"t" : NumberLong(7),
"h" : NumberLong(0),
"v" : 2,
"op" : "d",
"ns" : "db4.db4test",
"ui" : UUID("75507280-3f74-4c17-a3f7-46ce7087c08a"),
"wall" : ISODate("2020-08-14T07:13:08.162Z"),
"o" : {
"_id" : ObjectId("5f3628c809eccc387e65cd96")
}
}
/* 2 */
{
"ts" : Timestamp(1597389188, 2),
"t" : NumberLong(7),
"h" : NumberLong(0),
"v" : 2,
"op" : "d",
"ns" : "db4.db4test",
"ui" : UUID("75507280-3f74-4c17-a3f7-46ce7087c08a"),
"wall" : ISODate("2020-08-14T07:13:08.162Z"),
"o" : {
"_id" : ObjectId("5f3628c909eccc387e65cd97")
}
}

执行增量恢复:

# 先处理oplog,删除文件oplog.rs.metadata.json,修改oplog.rs.bson为oplog.bson
[root@mongo1 local]# pwd
/root/backup/oplog/local
[root@mongo1 local]# rm -rf oplog.rs.metadata.json
[root@mongo1 local]# mv oplog.rs.bson oplog.bson
[root@mongo1 local]# ls
oplog.bson # 执行恢复
mongorestore --authenticationDatabase admin -ulijiaman -plijiaman --port=27017 --oplogReplay --oplogLimit "1597389188:1" /root/backup/oplog/local

STEP9:查看数据是否恢复,确认已经完全恢复回来

rstest:PRIMARY> db.db4test.find()
{ "_id" : ObjectId("5f36267a09eccc387e65cd92"), "id" : 1111, "name" : "aaaa" }
{ "_id" : ObjectId("5f36267a09eccc387e65cd93"), "id" : 2222, "name" : "bbbb" }
{ "_id" : ObjectId("5f36267b09eccc387e65cd94"), "id" : 3333, "name" : "cccc" }
{ "_id" : ObjectId("5f3628c809eccc387e65cd95"), "id" : 4444, "name" : "dddd" }
{ "_id" : ObjectId("5f3639a009eccc387e65cd98"), "id" : 7777, "name" : "gggg" }
{ "_id" : ObjectId("5f3639a009eccc387e65cd99"), "id" : 8888, "name" : "hhhh" }
{ "_id" : ObjectId("5f3639a109eccc387e65cd9a"), "id" : 9999, "name" : "kkkk" }
{ "_id" : ObjectId("5f3628c809eccc387e65cd96"), "id" : 5555, "name" : "eeee" }
{ "_id" : ObjectId("5f3628c909eccc387e65cd97"), "id" : 6666, "name" : "ffff" }

【完】

2.MongoDB 4.2副本集环境基于时间点的恢复的更多相关文章

  1. 1.MongoDB 2.7主从复制(master –> slave)环境基于时间点的恢复

    (一)MongoDB恢复概述 对于任何类型的数据库,如果要将数据库恢复到过去的任意时间点,否需要有过去某个时间点的全备+全备之后的重做日志,MongoDB也不例外.使用全备将数据库恢复到固定时刻,然后 ...

  2. Mongodb主从复制 及 副本集+分片集群梳理

    转载努力哥原文,原文连接https://www.cnblogs.com/nulige/p/7613721.html 介绍了Mongodb的安装使用,在 MongoDB 中,有两种数据冗余方式,一种 是 ...

  3. 【六】MongoDB管理之副本集

    一.复制介绍 所谓的复制就是在多个主机之间同步数据的过程. 1.数据冗余及可用性 复制技术提供数据冗余及可用性,在不同的数据库服务器上使用多个数据副本,复制技术防止单个数据库服务器出现数据故障而出现数 ...

  4. mongodb系列之---副本集配置与说明

    在配置副本集之前,我们先来了解一些关于副本集的知识. 1,副本集的原理 副本集的原理与主从很相似,唯一不同的是,在主节点出现故障的时候,主从配置的从服务器不会自动的变为主服务器,而是要通过手动修改配置 ...

  5. MongoDB 复制(副本集)学习

    MongoDB 复制(副本集)学习 replication set复制集,复制集,多台服务器维护相同的数据副本,提高服务器的可用性.MongoDB复制是将数据同步在多个服务器的过程.复制提供了数据的冗 ...

  6. 表空间基于时间点的恢复(TSPITR)

    环境:RHEL 6.4 + Oracle 11.2.0.4 准备模拟环境 1. 验证表空间的依赖性 2. 确定执行TSPITR后会丢失的对象 3. 自动执行TSPITR Reference 准备模拟环 ...

  7. Oracle之表空间基于时间点的恢复

    记一次优化过程中:一次误操作,在不影响其他表空间的情况下:采用表空间基于时间点的恢复(TSPITR)方法恢复数据的过程. 1.TSPITR恢复原理    TSPITR目前最方便的方法是使用RMAN进行 ...

  8. MongoDB副本集replica set (二)--副本集环境搭建

    (一)主机信息 操作系统版本:centos7 64-bit 数据库版本   :MongoDB 4.2 社区版 ip hostname 192.168.10.41 mongoserver1 192.16 ...

  9. Mongodb 笔记06 副本集的组成、从应用程序连接副本集、管理

    副本集的组成 1. 同步:MongoDB的复制功能是使用操作日志oplog实现的,操作日志包含了主节点的每一次写操作.oplog是主节点的local数据库中的一个固定集合.备份节点通过查询整个集合就可 ...

随机推荐

  1. webview访问URL

    //    // Do any additional setup after loading the view. //    //创建WKWebView //    WKWebView *web = ...

  2. javascript中的堆栈、深拷贝和浅拷贝、闭包

    堆栈 在javascript中,堆内存是用来存放引用类型的空间环境 而栈内存,是存储基本类型和指定代码的环境 在对象中的属性名具有唯一性,数字属性名=字符串属性名,但是在测试的时候你会发现,好像所有属 ...

  3. 线程_进程间通信Queue合集

    # Queue的工作原理 from multiprocessing import Queue q = Queue(3)#初始化一个Queue对象,最多可接收3条put消息 q.put("In ...

  4. PHP imagealphablending - 设定图像的混色模式

    imagealphablending — 设定图像的混色模式.高佣联盟 www.cgewang.com 语法 bool imagealphablending ( resource $image , b ...

  5. PHP quoted_printable_encode() 函数

    定义和用法 quoted_printable_encode() 函数把 8 位字符串转换为 quoted-printable 字符串. 提示:经过 quoted-printable 编码后的数据与通过 ...

  6. SpringBoot2 整合 Swagger2文档 使用BootstrapUI页面

    SpringBoot2 整合 Swagger2 SpringBoot整合三板斧 第一步.引入pom <dependency> <groupId>com.spring4all&l ...

  7. 承诺会计/预留款会计(commitment accounting/Encumbrance Accounting) in AX 2012

    作者:umfish  博文 http://blog.csdn.net/umfish/article/details/7751397 如果要使用Encmubrance Accounting, 需要先在G ...

  8. 解决Jenkins的html样式不生效问题的终极方案

    本文从四个步骤来分享我们在自行搭建jenkins过程中遇到的报表样式不全(即html报告展示不正确)的问题: 1.问题现象 2.问题原因 3.问题原因补充 4.解决方法(可以直接跳到第四步解决问题) ...

  9. .Net Core 实体生成器

    实体生成器是什么? 实体生成器的功能就是自动将数据库中的表以及字段 转化成我们 高级编程语言中的实体类. 我们为什么要用实体生成器 在.net core开发环境下,我们可以使用efcore这个orm来 ...

  10. Python 超简单 提取音乐高潮(附批量提取)

    很多时候我们想提取某首歌的副歌部分(俗称 高潮部分),只能手动直接卡点剪切,但是对于大批量的获取就很头疼,如何解决? 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后 ...