MongoDB OpLog
作者:互联网
mongodump和mongorestore高级企业应用(--oplog)
注意:这是replica set或者master/slave模式专用
--oplog
use oplog for taking a point-in-time snapshot
# 可以备份基于时间点的快照
# 在做备份过程中,把新产生的数据,以oplog快照的形式进行保存
oplog介绍
在replica set中oplog是一个定容集合(capped collection),它的默认大小是磁盘空间的5%(可以通过--oplogSizeMB参数修改).
位于local库的db.oplog.rs,有兴趣可以看看里面到底有些什么内容。
其中记录的是整个mongod实例一段时间内数据库的所有变更(插入/更新/删除)操作。
当空间用完时新记录自动覆盖最老的记录。
其覆盖范围被称作oplog时间窗口。需要注意的是,因为oplog是一个定容集合,
所以时间窗口能覆盖的范围会因为你单位时间内的更新次数不同而变化。
想要查看当前的oplog时间窗口预计值,可以使用以下命令:
说明:
1、oplog相当于MySQL中的binlog,保存的是MongoDB修改操作类的日志
2、他是一个定容集合,也就是固定大小不变的表
3、默认可用大小是磁盘空间的5%,可以通过oplogsizeMB参数指定
4、单节点MongoDB没有oplog,只存在于复制集中
5、可以通过以下命令监控是否够用
my_repl:PRIMARY> rs.printReplicationInfo()
oplog 什么时候可以被覆盖?
至少要预留MongoDB一个全备的周期大小
或者计划任务,每几个小时备份一次oplog
启动一下复制集:
mongod -f /mongodb/28017/conf/mongod.conf
mongod -f /mongodb/28018/conf/mongod.conf
mongod -f /mongodb/28019/conf/mongod.conf
mongod -f /mongodb/28020/conf/mongod.conf
my_repl:PRIMARY> rs.printReplicationInfo()
configured oplog size: 2048MB <---集合大小
log length start to end: 80641secs (22.4hrs) <---预计窗口覆盖时间
oplog first event time: Sat Oct 24 2020 12:54:27 GMT+0800 (CST)
oplog last event time: Sun Oct 25 2020 11:18:28 GMT+0800 (CST)
now: Sun Oct 25 2020 11:18:37 GMT+0800 (CST)
my_repl:PRIMARY>
# oplog在哪?
my_repl:PRIMARY> use local
switched to db local
my_repl:PRIMARY> show tables;
me
oplog.rs #表名
replset.election
replset.minvalid
replset.oplogTruncateAfterPoint
startup_log
system.replset
system.rollback.id
my_repl:PRIMARY>
my_repl:PRIMARY>
my_repl:PRIMARY> db.oplog.rs.find().pretty()
{
"ts" : Timestamp(1603596973, 15),
"t" : NumberLong(2),
"h" : NumberLong("5601072907399108802"),
"v" : 2,
"op" : "i",
"ns" : "simon.foo",
"ui" : UUID("82000b1b-359c-4cc2-84a7-3be775b518a1"),
"wall" : ISODate("2020-10-25T03:36:13.813Z"),
"o" : {
"_id" : ObjectId("5f94f2ad1e125066f9568858"),
"a" : 13
}
}
"ts" : Timestamp(1553597844, 1), //(时间戳 + 操作序列号) --->相当于GTID
"op" : "n" //操作类型
"ns" : //操作对象
"o" :
# 操作类型
"i": insert
"u": update
"d": delete
"c": db cmd
"n": NOTE 提示类操作,可以不用关注
# 查看 Create 类操作
my_repl:PRIMARY> db.oplog.rs.find( { "op" : "c"} ).pretty()
# 查看 insert 类操作
my_repl:PRIMARY> db.oplog.rs.find({"op":"i"}).pretty()
test:PRIMARY> rs.printReplicationInfo()
configured oplog size: 1561.5615234375MB <--集合大小
log length start to end: 423849secs (117.74hrs) <--预计窗口覆盖时间
oplog first event time: Wed Sep 09 2015 17:39:50 GMT+0800 (CST)
oplog last event time: Mon Sep 14 2015 15:23:59 GMT+0800 (CST)
now: Mon Sep 14 2015 16:37:30 GMT+0800 (CST)
oplog企业级应用
(1)实现热备,在备份时使用--oplog选项
注:为了演示效果我们在备份过程,模拟数据插入
(2)准备测试数据
[mongod@db01 conf]$ mongo --port 28018
use oldboy
for(var i = 1 ;i < 100; i++) {
db.foo.insert({a:i});
}
my_repl:PRIMARY> db.oplog.rs.find({"op":"i"}).pretty()
oplog 配合mongodump实现热备
mkdir -p /mongodb/backup/opdata
mongodump --port 28017 --gzip --oplog -o /mongodb/backup/opdata
[mongod@mysql-node01 ~]$ mongodump --port 28017 --gzip --oplog -o /mongodb/backup/opdata/
2020-10-25T11:42:11.254+0800 writing admin.system.version to
2020-10-25T11:42:11.254+0800 done dumping admin.system.version (1 document)
2020-10-25T11:42:11.255+0800 writing simon.foo to
2020-10-25T11:42:11.255+0800 done dumping simon.foo (99 documents)
2020-10-25T11:42:11.256+0800 writing captured oplog to
2020-10-25T11:42:11.256+0800 dumped 1 oplog entry
[mongod@mysql-node01 ~]$
[mongod@mysql-node01 ~]$
[mongod@mysql-node01 ~]$ cd /mongodb/backup/opdata
[mongod@mysql-node01 opdata]$ pwd
/mongodb/backup/opdata
[mongod@mysql-node01 opdata]$ ll
total 4
drwxrwxr-x 2 mongod mongod 75 Oct 25 11:46 admin
-rw-rw-r-- 1 mongod mongod 118 Oct 25 11:46 oplog.bson
drwxrwxr-x 2 mongod mongod 53 Oct 25 11:46 simon
[mongod@mysql-node01 opdata]$
作用介绍:--oplog 会记录备份过程中的数据变化,以快照的形式保存在oplog.bson里
恢复
mongorestore --port 28017 --oplogReplay /mongodb/backup/opdata
--oplogReplay # 恢复完数据文件后再重放oplog。默认回放文件是当前目录下 dump/oplog.bson
# <dump-directory>/local/oplog.rs.bson
如果oplog不在这,则可以通过下面参数指定
--oplogFile # 指定需要重放的oplog文件位置
--oplogLimit # 重放oplog 时截止到指定时间点
# 为了模拟dump过程中的数据变化,我们开启一个循环插入数据的线程:
# 一个窗口模拟数据插入
for (var i=0; i<100000; i++){
db.random.insertOne({x:Math.random()*100000});
}
# 另一个窗口 对MongoDB做 mongodump
mongodump -h localhost:27017 --oplog
oplog高级应用
背景:每天0点全备,oplog恢复窗口为48小时
某天,上午10点world.city 业务表被误删除。
恢复思路:
0、停应用
2、找测试库
3、恢复昨天晚上全备
4、截取全备之后到world.city误删除时间点的oplog,并恢复到测试库
5、将误删除表导出,恢复到生产库
恢复步骤:
模拟故障环境:
1、全备数据库
模拟原始数据
mongo --port 28017
my_repl:PRIMARY> use simon_db
switched to db simon_db
my_repl:PRIMARY> for(var i = 1 ;i < 20; i++) {
... db.t1.insert({a: i});
... }
WriteResult({ "nInserted" : 1 })
my_repl:PRIMARY>
全备:
rm -rf /mongodb/backup/*
mongodump --port 28017 --oplog -o /mongodb/backup/opdata
--oplog功能:在备份同时,将备份过程中产生的日志进行备份
文件必须存放在/mongodb/backup下,自动命令为oplog.bson
[mongod@mysql-node01 backup]$ mongodump --port 28017 --oplog -o /mongodb/backup/opdata
2020-10-25T12:24:21.806+0800 writing admin.system.version to
2020-10-25T12:24:21.807+0800 done dumping admin.system.version (1 document)
2020-10-25T12:24:21.807+0800 writing simon.foo to
2020-10-25T12:24:21.808+0800 writing simon_db.t1 to
2020-10-25T12:24:21.808+0800 writing test.t1 to
2020-10-25T12:24:21.808+0800 writing test.t3 to
2020-10-25T12:24:21.809+0800 done dumping simon_db.t1 (19 documents)
2020-10-25T12:24:21.809+0800 writing test.t2 to
2020-10-25T12:24:21.809+0800 done dumping simon.foo (99 documents)
2020-10-25T12:24:21.809+0800 done dumping test.t2 (1 document)
2020-10-25T12:24:21.809+0800 done dumping test.t3 (1 document)
2020-10-25T12:24:21.809+0800 done dumping test.t1 (19 documents)
2020-10-25T12:24:21.810+0800 writing captured oplog to
2020-10-25T12:24:21.810+0800 dumped 1 oplog entry
[mongod@mysql-node01 backup]$
再次模拟数据
use simon_db
db.t2.insert({id:1})
db.t3.insert({id:2})
2、上午10点:删除wo库下的ci表
10:00时刻,误删除
my_repl:PRIMARY> db.t1.drop()
true
my_repl:PRIMARY>
my_repl:PRIMARY> show tables
t2
t3
my_repl:PRIMARY>
3、备份现有的oplog.rs表
mongodump --port 28017 -d local -c oplog.rs -o /mongodb/backup/oplog
[mongod@mysql-node01 opdata]$ mongodump --port 28017 -d local -c oplog.rs -o /mongodb/backup/oplog
2020-10-25T12:27:25.481+0800 writing local.oplog.rs to
2020-10-25T12:27:25.488+0800 done dumping local.oplog.rs (2508 documents)
[mongod@mysql-node01 opdata]$
[mongod@mysql-node01 local]$ cd /mongodb/backup/oplog/
[mongod@mysql-node01 oplog]$ ll local/
total 292
-rw-rw-r-- 1 mongod mongod 293813 Oct 25 12:27 oplog.rs.bson
-rw-rw-r-- 1 mongod mongod 125 Oct 25 12:27 oplog.rs.metadata.json
[mongod@mysql-node01 oplog]$
4、截取oplog并恢复到drop之前的位置
更合理的方法:登陆到原数据库
[mongod@mysql-node01 oplog]$ mongo --port 28017
my_repl:PRIMARY> use local
my_repl:PRIMARY> db.oplog.rs.find({"op":"c"}).pretty()
{
"ts" : Timestamp(1603599960, 1),
"t" : NumberLong(2),
"h" : NumberLong("3370511625250650296"),
"v" : 2,
"op" : "c",
"ns" : "simon_db.$cmd",
"ui" : UUID("9d0650c5-cba0-4747-ad30-4195b5204aa3"),
"wall" : ISODate("2020-10-25T04:26:00.989Z"),
"o" : {
"drop" : "t1"
}
}
获取到oplog误删除时间点位置:
"ts" : Timestamp(1603599960, 1)
5、恢复备份+应用oplog
# 挪走备份时间点的oplog
[mongod@mysql-node01 opdata]$ mv oplog.bson /tmp/
# 把刚才导出的oplog信息cp到全备文件
[mongod@mysql-node01 opdata]$ cd /mongodb/backup/oplog/local/
[mongod@mysql-node01 local]$ ls
oplog.rs.bson oplog.rs.metadata.json
[mongod@mysql-node01 local]$
[mongod@mysql-node01 local]$ cp oplog.rs.bson /mongodb/backup/opdata/oplog.bson
[mongod@mysql-node01 local]$ ll /mongodb/backup/opdata/
total 288
drwxrwxr-x 2 mongod mongod 69 Oct 25 12:24 admin
-rw-rw-r-- 1 mongod mongod 293813 Oct 25 12:36 oplog.bson
drwxrwxr-x 2 mongod mongod 47 Oct 25 12:24 simon
drwxrwxr-x 2 mongod mongod 45 Oct 25 12:24 simon_db
drwxrwxr-x 2 mongod mongod 123 Oct 25 12:24 test
[mongod@mysql-node01 local]$
mongorestore --port 28017 --oplogReplay --oplogLimit "1603599960:1" --drop /mongodb/backup/opdata/
# --oplogLimit "1603599960:1" 只恢复指定的时间戳之前的记录
# 这里是测试环境,所以加了--drop参数,删除库里的原集合,再重新创建
# 生产环境,要用备份恢复到非生产环境节点,再把要恢复的数据导出导入到线上
[mongod@mysql-node01 local]$ mongorestore --port 28017 --oplogReplay --oplogLimit "1603599960:1" --drop /mongodb/backup/opdata/
2020-10-25T12:39:02.021+0800 preparing collections to restore from
2020-10-25T12:39:02.022+0800 reading metadata for simon.foo from /mongodb/backup/opdata/simon/foo.metadata.json
2020-10-25T12:39:02.023+0800 reading metadata for simon_db.t1 from /mongodb/backup/opdata/simon_db/t1.metadata.json
2020-10-25T12:39:02.024+0800 reading metadata for test.t1 from /mongodb/backup/opdata/test/t1.metadata.json
2020-10-25T12:39:02.031+0800 restoring simon.foo from /mongodb/backup/opdata/simon/foo.bson
2020-10-25T12:39:02.041+0800 restoring test.t1 from /mongodb/backup/opdata/test/t1.bson
2020-10-25T12:39:02.042+0800 reading metadata for test.t2 from /mongodb/backup/opdata/test/t2.metadata.json
2020-10-25T12:39:02.045+0800 restoring simon_db.t1 from /mongodb/backup/opdata/simon_db/t1.bson
2020-10-25T12:39:02.055+0800 restoring test.t2 from /mongodb/backup/opdata/test/t2.bson
2020-10-25T12:39:02.074+0800 no indexes to restore
2020-10-25T12:39:02.074+0800 finished restoring simon_db.t1 (19 documents)
2020-10-25T12:39:02.075+0800 reading metadata for test.t3 from /mongodb/backup/opdata/test/t3.metadata.json
2020-10-25T12:39:02.075+0800 no indexes to restore
2020-10-25T12:39:02.075+0800 finished restoring simon.foo (99 documents)
2020-10-25T12:39:02.082+0800 restoring test.t3 from /mongodb/backup/opdata/test/t3.bson
2020-10-25T12:39:02.084+0800 no indexes to restore
2020-10-25T12:39:02.084+0800 finished restoring test.t1 (19 documents)
2020-10-25T12:39:02.084+0800 no indexes to restore
2020-10-25T12:39:02.084+0800 finished restoring test.t2 (1 document)
2020-10-25T12:39:02.092+0800 no indexes to restore
2020-10-25T12:39:02.092+0800 finished restoring test.t3 (1 document)
2020-10-25T12:39:02.092+0800 replaying oplog
2020-10-25T12:39:02.187+0800 done
[mongod@mysql-node01 local]$
# 登陆MongoDB查看
[mongod@mysql-node01 local]$ mongo --port 28017
my_repl:PRIMARY>
my_repl:PRIMARY>
my_repl:PRIMARY> use simon_db
switched to db simon_db
my_repl:PRIMARY> show tables
t1
t2
t3
my_repl:PRIMARY>
my_repl:PRIMARY> db.t1.count()
19
my_repl:PRIMARY>
扩展命令:
https://docs.mongodb.com/v3.6/reference/program/bsondump/
bsondump 可以将bson格式的数据转换成json
然后用mongoimport 导入
[mongod@mysql-node01 local]$ bsondump oplog.rs.bson
分片集群的备份思路(了解)
方案一:社区版 直接通过mongos进行备份。
mongos可以进行完整备份,只能对单一节点进行恢复。如果是两个shard分片节点,那就相当于要推倒shard节点进行重构。
方案二:企业版(收费),专门的备份工具,Ops manager,可以对单一分片、集群当中的所有关键节点进行备份。还可以实现部分恢复
方案三:自己开发分布式备份系统
尽管理论上我们可以使用与复制集同样的方式来为分片集完成增量备份,但实际上分片集的情况更加复杂。这种复杂性来自两个方面:
- 各个数据节点的时间不一致:每个数据节点很难完全恢复到一个真正的一致时间点上,通常只能做到大致一致,而这种大致一致通常足够好,除了以下情况;
- 分片间的数据迁移:当一部分数据从一个片迁移到另一个片时,最终数据到底在哪里取决于config中的元数据。如果元数据与数据节点之间的时间差异正好导致数据实际已经迁移到新分片上,而元数据仍然认为数据在旧分片上,就会导致数据丢失情况发生。虽然这种情况发生的概率很小,但仍有可能导致问题。
要避免上述问题的发生,只有定期停止均衡器;只有在均衡器停止期间,增量恢复才能保证正确。
1、你要备份什么?
config server
shard 节点
单独进行备份
2、备份有什么困难和问题
(1)chunk迁移的问题
人为控制在备份的时候,避开迁移的时间窗口
(2)shard节点之间的数据不在同一时间点。
选业务量较少的时候,把configserver,各个shard节点摘除从节点。
关于备份分片集群,官方给出的思路:
1、stop Balancer(and w ait) # 停止balancer
2、or no balancing window # 或者开启一个没有balancing的空窗口
3、stop on config server、Shard node (data R/O) # 停掉一个configserver和shard node
4、backup data (shards,config) # 备份shards、config 数据
5、restart config server、shard node # 再把节点加入到MSC集群
6、Resume balancer
恢复:
1、Dissmilar #shards to restore to
2、Different shard keys?
3、selective restores
4、consolidate shards
5、changing addresses of config/shards
Ops Manager
标签:10,mongod,--,MongoDB,0800,oplog,2020,OpLog 来源: https://www.cnblogs.com/oldSimon/p/16290813.html