Mongodb副本集基于oplog的增量备份和恢复
2020-06-16 本文已影响0人
Odven
1) oplog介绍
在replica set中oplog是一个定容集合(capped collection),它的默认大小是磁盘空间的5%(可以通过--oplogSizeMB参数修改).
位于local库的db.oplog.rs,有兴趣可以看看里面到底有些什么内容。
其中记录的是整个mongod实例一段时间内数据库的所有变更(插入/更新/删除)操作。
当空间用完时新记录自动覆盖最老的记录。
其覆盖范围被称作oplog时间窗口。需要注意的是,因为oplog是一个定容集合,
所以时间窗口能覆盖的范围会因为你单位时间内的更新次数不同而变化。
想要查看当前的oplog时间窗口预计值,可以使用以下命令:
shard1:PRIMARY> rs.printReplicationInfo()
configured oplog size: 256MB <--集合大小
log length start to end: 18582secs (5.16hrs) <--预计窗口覆盖时间
oplog first event time: Mon Jun 15 2020 10:08:43 GMT+0800 (CST)
oplog last event time: Mon Jun 15 2020 15:18:25 GMT+0800 (CST)
now: Mon Jun 15 2020 15:18:30 GMT+0800 (CST)
shard1:PRIMARY> rs.printSlaveReplicationInfo()
source: 192.168.137.50:27081 <-- 主(主从复制的源)
syncedTo: Mon Jun 15 2020 15:18:15 GMT+0800 (CST)
0 secs (0 hrs) behind the primary <-- 落后主多长时间
use local
db.oplog.rs.find().pretty()
"ts" : Timestamp(1553597844, 1),
"op" : "n"
"o" :
"op" : 看是什么类型的操作
"i": insert
"u": update
"d": delete
"c": db cmd
2) oplog企业级应用
1. 实现热备,在备份时使用--oplog选项
作用介绍:--oplog 会记录备份过程中的数据变化。会以oplog.bson保存下来
mongodump -h 192.168.137.50 --port 27080 -uroot -p123 --authenticationDatabase=admin --oplog -o /root/mongodb_dir/all_back/ # 全备,使用oplog拍摄时间点快照(会把备份开始到备份结束这段时间里的数据变化备份,当数据导入时使用--oplogReplay重做日志) 这是replica set或者master/slave模式专用
2. 恢复
mongorestore -h 192.168.137.50 --port 27080 -uroot -p123 --authenticationDatabase=admin --oplogReplay /root/mongodb_dir/all_back/ # 使用--oplogReplay重做日志
3. 故障示例演练
背景:每天0点全备,oplog恢复窗口为48小时
某天,上午10点gy.users 用户表被误删除。
恢复思路:
1、停应用
2、找测试库
3、恢复昨天晚上全备
4、截取全备之后到world.city误删除时间点的oplog,并恢复到测试库
5、将误删除表导出,恢复到生产库
恢复步骤:
模拟故障环境:
(1) 模拟原始数据
shard1:PRIMARY> use gy
switched to db gy
shard1:PRIMARY> for(i=1;i<=100;i++){db.users.insert({"name": "lisi", age: i, created_time: new Date()})}
WriteResult({ "nInserted" : 1 })
(2) 全备
mongodump -h 192.168.137.50 --port 27080 -uroot -p123 --authenticationDatabase=admin --oplog -o /root/mongodb_dir/all # --oplog功能:在备份同时,将备份过程中产生的日志进行备份
(3) 再次模拟数据
shard1:PRIMARY> for(i=90;i<=100;i++){db.users.insert({"name": "zhangsan", age: i, created_time: new Date()})}
WriteResult({ "nInserted" : 1 })
(4) 上午10点:删除gy库下的users表
10:00时刻,误删除
shard1:PRIMARY> db.users.drop()
true
shard1:PRIMARY> show tables;
(5) 备份现有的oplog.rs表
mongodump -h 192.168.137.50 --port 27080 -uroot -p123 --authenticationDatabase=admin -d local -c oplog.rs -o /root/mongodb_dir/
(6) 截取oplog并恢复到drop之前的位置
方法一:
bsondump /root/mongodb_dir/local/oplog.rs.bson | grep "\"op\":\"c\"" | grep "drop"
获取到oplog误删除时间点位置: "ts":{"$timestamp":{"t":1592207452,"i":1}
方法二:
登陆到原数据库
shard1:PRIMARY> use local
switched to db local
shard1:PRIMARY> db.oplog.rs.count()
3076
shard1:PRIMARY> db.oplog.rs.find({"op": "c"}).sort({"ts": -1}).limit(1)
{ "ts" : Timestamp(1592207452, 1), "t" : NumberLong(4), "h" : NumberLong(0), "v" : 2, "op" : "c", "ns" : "gy.$cmd", "ui" : UUID("f084fc41-949d-497f-9c8c-4f7ac105530e"), "o2" : { "numRecords" : 111 }, "wall" : ISODate("2020-06-15T07:50:52.381Z"), "o" : { "drop" : "users" } }
获取到oplog误删除时间点位置:"ts" : Timestamp(1592207452, 1)
(7) 恢复备份+应用oplog
(7.1) 因为每天0点全备,oplog恢复窗口为48小时,所以可以把备份出来的oplog.rs.bson覆盖全备时的oplog.bson
cd /root/mongodb_dir/local/
ls
oplog.rs.bson oplog.rs.metadata.json
cp oplog.rs.bson /root/mongodb_dir/all/
admin/ gy/ oplog.bson
cp oplog.rs.bson /root/mongodb_dir/all/oplog.bson
cp: overwrite ‘/root/mongodb_dir/all/oplog.bson’? y
(7.2) 先恢复到27083这个副本集上并且27083这个副本集不能开启密码密码认证(重点)
mongorestore -h 192.168.137.50 --port 27083 --oplogReplay --oplogLimit "1592207452:1" --drop /root/mongodb_dir/all/
(7.3) 从27083这个副本集中导出想要的数据
mongodump -h 192.168.137.50 --port 27083 -d gy -c users -o /root/mongodb_dir/
(7.4) 把误删除的数据导入到27080副本集
mongorestore -h 192.168.137.50 --port 27080 -uroot -p123 --authenticationDatabase=admin /root/mongodb_dir/gy/users.bson
3) 关于使用oplog恢复的几种情况
1. 假设备份开始时间为 A 结束时间为B;等备份完成后,如果此时业务又insert了数据或update了数据;在时间 C点,模拟误删除操作
2. 这种情况下,应该首先停止业务,避免由于业务量大,导致把oprlog给覆盖了,因为如果oprlog被覆盖了,那么你就无法恢复出db.gy.insert({"name": "wangwu", "age": 30})这条数据,因为这条数据是在你备份完成后插入的数据,所以你需要立刻把oplog.rs集合给dump出来以便于进行时间点恢复。
3. 所以分两种情况具体如下:
情况一:
你备份开始的时间点A 到 你误删除的时间点C 这段时间的oplog.rs的数据没有被覆盖那么就肯定能恢复出所有的数据!直接用你后来备份的oplog.rs.bson替换你之前全备份的产生的oplog.bson文件,然后恢复时使用--oplogReplay和--oplogLimit参数直接恢复
情况二:(分成两种情况)
如果你备份开始的时间点A 到 你误删除的时间点C 这段时间的oplog.rs的数据被覆盖了,那么你就只能先恢复你的全备,然后再从oplog.rs里面尽可能找到更多的关于这个集合的操作,然后应用,能不能全部恢复出数据,就看运气了,这里又有两种情况:
情况1:备份结束B到误删除C 这段时间内的oplog.rs没有被覆盖,那么就可以恢复出所有的数据
(1) 恢复一致性全备
mongorestore -h 192.168.137.50 --port 27083 --oplogReplay /root/mongodb_dir/full/
(2) 恢复最全的oplog
mongorestore -h 192.168.137.50 --port 27083 --oplogReplay --oplogLimit "1592274936:1" /root/mongodb_dir/local/oplog.rs.bson
情况2:备份结束B到误删除C 这段时间内的oplog.rs被覆盖,那么就只能期待关于这个集合的操作的oplog没有被覆盖,这样才能恢复出所有的数据!(恢复方法和上面一样)