一 研究背景需求
目前作者所在公司的MongoDB数据库是每天凌晨做一次全库完整备份,但数据库出现故障时,只能保证恢复到全备时间点,比如,00:30 做的完整备份,而出现故障是下午18:00,那么现有的备份机制只可以恢复到00:30,即丢失00:30 – 18:00 的操作数据。
此外,我们现在的副本集没有delay节点,当出现误操作或需要恢复到指定时间点操作时,目前灾备机制也不支持此操作。上线这种备份方案,心里总是惶惶的。
并且细究mongodump机制原理,此命令在运行过程中并不会把数据库锁死(或建立快照,以保证整个库冻结在一个固定的时间点),实现数据库完整性,而是细化到集合级别,如此,会导致数据完整性问题。 例如,集合A中存放了订单概要信息,集合B中存放了订单的所有明细,那么只有一个订单有完整的明细时才是正确的状态。那么备份时,如果备份集合A处于时间点x,而备份集合B处于x之后的一个时间点y时,可以想象A和B中的数据极有可能不对应而失去意义(部分订单有订单明细而没有订单概要信息)。
二 原理分析关系型数据库,例如MySQL ,SQL Server 都有事务日志(或bin log),会将数据库的DML 、 DDL、DCL等操作记录在事务文件中,可以通过日志备份搭建还原体系。MongoDB没有此类机制和数据文件,难以实现。
但MongoDB 副本集 有通过 oplog(主要记录在local数据库oplog.rs集合中) 实现节点间的同步,此集合记录了数据库的OP操作,记录的是整个mongod实例一段时间内的所有变更(插入/更新/删除)操作。
是否可以考虑通过oplog.rs集合的备份还原来解决以上问题(数据完整性;不能还原到指定时间点;时效性差。)。
值得注意的是,oplog为replica set或者master/slave模式专用,standalone模式运行mongodb并不推荐。
查看mongodb备份命令Mongodump,其中有一个相关参数oplog。
Mongodump 中--oplog参数
参数
参数说明
--oplog
Use oplog for taking a point-in-time snapshot
该参数的主要作用是我们在导出库集合数据的同时生成一个oplog.bson文件,里面存放了开始进行dump到dump结束之间所有的op log 操作。
注意:--oplog选项只对全库导出有效。
相应的 Mongorestore 中与 Oplog 相关的参数
参数
参数说明
oplogReplay
replay oplog for point-in-time restore
oplogLimit
only include oplog entries before the provided Timestamp
oplogFile
oplog file to use for replay of oplog
三 验证测试
3.1 场景1 备份还原后,如何保证数据一致性、完整性
在Insert数据过程中,备份数据库,为说明问题,数据插入跨越整个备份过程。
3.1.1 在不使用--oplog 参数下备份还原
Step 1 向数据库ygtest041602插入数据,源库没有集合order0531、orderdetial
插入语句:
for(var i = 0; i < 10000; i++)
{ db.order0531.insert({a: i});};
for(i=0;i<300000;i++)
{ db.orderdetial.insert({"id":i,"name":"shenzheng","addr":"龙岗","date":new Date()}); };
step 2 在上述命令执行期间 执行mongodump 备份
./mongodump -h 172.177.XXX.XXX --port 端口 --authenticationDatabase admin -u 用户名 -p 密码 --gzip -o /data/mongodb_back/mongotestdump
Step 3 还原上述备份文件
./mongorestore -h 172.177.XXX.XXX --port 端口 --authenticationDatabase admin -u 用户名 -p 密码 --gzip /data/mongodb_back/mongotestdump
Step 4 检查源库Insert 语句, 执行完毕(一定是mongodump完毕,再insert结束;但不强调,mongorestore与insert的时间关系)
Step 5 待语句执行完毕后,比较 源库和 还原库 的数据。
源库