数据库
首页 > 数据库> > MongoDB OpLog

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,可以对单一分片、集群当中的所有关键节点进行备份。还可以实现部分恢复

方案三:自己开发分布式备份系统

尽管理论上我们可以使用与复制集同样的方式来为分片集完成增量备份,但实际上分片集的情况更加复杂。这种复杂性来自两个方面:

要避免上述问题的发生,只有定期停止均衡器;只有在均衡器停止期间,增量恢复才能保证正确。

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