zoukankan      html  css  js  c++  java
  • MongoDB备份(mongodump)与恢复(mongorestore)工具实践

    mongodump和mongorestore实践

    1.mongodump备份工具

    • mongodump能够在Mongodb运行时进行备份,它的工作原理是对运行的Mongodb做查询,然后将所有查到的文档写入磁盘。
    • mongodump的参数与mongoexport的参数基本一致

    1.1 mongodump关键参数如下所示:

    mongodump --help查看帮助命令

    • -h,--host :代表远程连接的数据库地址,默认连接本地Mongo数据库;
    • --port:代表远程连接的数据库的端口,默认连接的远程端口27017;
    • -u,--username:代表连接远程数据库的账号,如果设置数据库的认证,需要指定用户账号;
    • -p,--password:代表连接数据库的账号对应的密码;
    • -d,--db:代表连接的数据库;
    • -c,--collection:代表连接数据库中的集合;
    • -o, --out:代表导出的文件输出目录;
    • -q, --query:代表查询条件;
    • -j,--numParallelCollections =要并行转储的集合数(默认为4)
    • --gzip,使用Gzip压缩存档;
    • --oplog,使用oplog进行时间点快照;
    • --authenticationDatabase,指定用户鉴定库

    1.2 mongodump参数实践

    全库备份
    mongodump -u -p --port 28020 --authenticationDatabase admin -o /tmp/backup
    
    备份指定的库,test库
    mongodump -u -p --port 28020 --authenticationDatabase admin -d test -o /tmp/backup
    
    备份test库下的customer集合
    mongodump -u -p --port 28020 --authenticationDatabase admin -d test -c customer -o /tmp/backup
    
    压缩备份
    压缩备份单库
    mongodump -u -p --port 28020 --authenticationDatabase admin -d test -o /tmp/backup --gzip
    
    压缩备份单表
    mongodump -u -p --port 28020 --authenticationDatabase admin -d test -c customer -o /tmp/backup --gzip
    

    2.mongorestore恢复工具

    2.1 mongorestore关键参数如下所示:

    mongodump --help查看帮助命令

    • -h,--host :代表远程连接的数据库地址,默认连接本地Mongo数据库;
    • --port:代表远程连接的数据库的端口,默认连接的远程端口27017;
    • -u,--username:代表连接远程数据库的账号,如果设置数据库的认证,需要指定用户账号;
    • -p,--password:代表连接数据库的账号对应的密码;
    • -d,--db:代表连接的数据库;
    • -c,--collection:代表连接数据库中的集合;
    • -o, --out:代表导出的文件输出目录;
    • --dir = <目录名称>输入目录
    • --drop导入前删除数据库中集合;
    • --gzip,解压Gzip压缩存档还原;
    • --oplog,重放oplog以基于时间点还原;
    • --oplogFile = <文件名>指定重播oplog的oplog文件
    • --authenticationDatabase,指定用户鉴定库

    2.2 mongorestore参数实践

    单库恢复
    mongorestore -u -p --port 28018 --authenticationDatabase admin -d test /tmp/backup/test
    
    恢复test库下的customer集合
    mongorestore -u -p --port 28018 --authenticationDatabase admin -d test -c customer /tmp/backup/test/customer.bson
    
    --drop参数实践恢复

    恢复的时候,先删除当前数据,然后恢复备份的数据。就是说,备份后添加修改的数据都会被删除,谨慎使用!!!

    # 恢复单库
    mongorestore -u -p --port 28018 --authenticationDatabase admin -d test --drop /tmp/backup/test
    
    # 恢复单表
    mongorestore -u -p --port 28018 --authenticationDatabase admin -d test -c customer --drop /tmp/backup/test/customer.bson 
    
    --gzip参数实践恢复
    mongorestore -u -p --port 28018 --authenticationDatabase admin --gzip /tmp/backup
    

    3.MongoDB中的oplog

    3.1 什么是oplog

    • 当Primary进行写操作的时候,会将这些写操作记录写入Primary的Oplog中,而后Secondary会将Oplog 复制到本机并应用这些操作,从而实现Replication的功能。
    • 同时由于其记录了Primary上的写操作,故还能将其用作数据恢复。
    • 可以简单的将其视作Mysql中的binlog。
    • oplog为replica set或者master/slave模式专用(standalone模式运行mongodb并不推荐)

    3.2 oplog相关的操作

    • 在replica set中oplog是一个定容集合(capped collection),它的默认大小是磁盘空间的5%(可以通过--oplogSizeMB参数修改)
    • 其中记录的是整个mongod实例一段时间内数据库的所有变更(插入/更新/删除)操作。当空间用完时新记录自动覆盖最老的记录。
    oplog的位置:
    oplog在local库: local.oplog
    
    master/slave 架构下:local.oplog.$main;
    
    replica sets 架构下:local.oplog.rs
    
    oplog时间窗口覆盖时间
    easydb:PRIMARY> rs.printReplicationInfo()
    configured oplog size:   2048MB   <--集合大小
    log length start to end: 524592secs (145.72hrs)  <--预计窗口覆盖时间
    oplog first event time:  Fri Jan 08 2021 18:30:18 GMT+0800 (CST)
    oplog last event time:   Thu Jan 14 2021 20:13:30 GMT+0800 (CST)
    now:                     Thu Jan 14 2021 20:13:35 GMT+0800 (CST)
    
    查看oplog内容
    easydb:PRIMARY> use local
    easydb:PRIMARY> db.oplog.rs.find().pretty()
    {
    	"ts" : Timestamp(1610101818, 1),
    	"h" : NumberLong("-124421688313536398"),
    	"v" : 2,
    	"op" : "n",
    	"ns" : "",
    	"wall" : ISODate("2021-01-08T10:30:18.329Z"),
    	"o" : {
    		"msg" : "initiating set"
    	}
    }
    
    

    3.3 oplog数据结构

    下面来分析一下oplog中字段的含义,通过下面的命令取出一条oplog:

    db.oplog.rs.find().skip(1).limit(1).toArray()

    easydb:PRIMARY> use local
    switched to db local
    easydb:PRIMARY> db.oplog.rs.find().skip(1).limit(1).toArray()
    [
    	{
    		"ts" : Timestamp(1610101831, 1),
    		"t" : NumberLong(1),
    		"h" : NumberLong("-5190685117971188188"),
    		"v" : 2,
    		"op" : "n",
    		"ns" : "",
    		"wall" : ISODate("2021-01-08T10:30:31.356Z"),
    		"o" : {
    			"msg" : "new primary"
    		}
    	}
    ]
    
    
    • ts: 8字节的时间戳,由4字节unix timestamp + 4字节自增计数表示。这个值很重要,在选举(如master宕机时)新primary时,会选择ts最大的那个secondary作为新primary
    • op:1字节的操作类型
      • "i": insert
      • "u": update
      • "d": delete
      • "c": db cmd
      • "db":声明当前数据库 (其中ns 被设置成为=>数据库名称+ '.')
      • "n": no op,即空操作,其会定期执行以确保时效性
    • ns:操作所在的namespace
    • o:操作所对应的document,即当前操作的内容(比如更新操作时要更新的的字段和值)
    • o2: 在执行更新操作时的where条件,仅限于update时才有该属性

    3.4 --oplog参数说明

    mongodump --oplog参数说明
    [root@mysql02 ~]# mongodump --help
    --oplog     use oplog for taking a point-in-time snapshot
    
    mongorestore --oplog参数说明
    参数 参数说明
    --oplogReplay 重放oplog.bson中的操作内容
    --oplogLimit 与--oplogReplay一起使用时,可以限制重放到指定的时间点

    3.5 mongodump使用--oplog参数备份

    首先我们在mongodb中模拟一个不断有插入操作的集合foo

    use test
    for(var i = 0; i < 10000; i++) {
        db.foo.insert({a: i});
    }
    

    然后在插入过程中模拟一次mongodump全备,并添加--oplog参数

    [root@mysql02 ~]# mongodump -u -p --port 28018 --authenticationDatabase admin --oplog -o /tmp/backup
    2021-01-14T20:51:15.254+0800	writing admin.system.version to 
    2021-01-14T20:51:15.255+0800	done dumping admin.system.version (1 document)
    2021-01-14T20:51:15.255+0800	writing test.foo to 
    2021-01-14T20:51:15.474+0800	done dumping test.foo (1701 documents)
    2021-01-14T20:51:15.483+0800	writing captured oplog to 
    2021-01-14T20:51:15.509+0800		dumped 73 oplog entries
    
    
    [root@mysql02 ~]# ll /tmp/backup
    总用量 12
    drwxr-xr-x 2 root root    69 1月  14 20:51 admin
    -rw-r--r-- 1 root root 10804 1月  14 20:51 oplog.bson
    drwxr-xr-x 2 root root    47 1月  14 20:51 test
    
    从dump开始到结束的时间系统将记录所有的oplog到oplog.bson文件中
    

    注意:--oplog选项只对全库导出有效,所以不能指定-d选项。

    3.6 mongorestore使用--oplog参数恢复

    [root@mysql02 ~]# mongorestore -u -p --port 28018 --authenticationDatabase admin --oplogReplay --drop /tmp/backup
    2021-01-14T21:13:52.134+0800	preparing collections to restore from
    2021-01-14T21:13:52.144+0800	reading metadata for test.foo from /tmp/backup/test/foo.metadata.json
    2021-01-14T21:13:52.199+0800	restoring test.foo from /tmp/backup/test/foo.bson
    2021-01-14T21:13:52.291+0800	no indexes to restore
    2021-01-14T21:13:52.291+0800	finished restoring test.foo (1701 documents)  <--表示test.foo集合中恢复了1701个文档
    2021-01-14T21:13:52.291+0800	replaying oplog  <--表示重放了oplog中的所有操作
    2021-01-14T21:13:52.407+0800	done
    
    
    easydb:PRIMARY> db.foo.count()
    1771  <--所以实际比1701个多,因为应用了oplog中的数据
    
    
    这就是 oplog 配合 mongodump 实现热备功能

    4.利用oplog实现任意时间点数据恢复

    oplog有两种来源:

    • mongodump时加上--oplog选项,自动生成的oplog,这种方式的oplog直接 --oplogReplay 就可以恢复
    • 单独备份获取的oplog

    例如:

    mongodump  --port 28021 -d local -c oplog.rs
    

    4.1 模拟一个持续写入的生产环境

    easydb:PRIMARY> use test
    switched to db test
    
    easydb:PRIMARY> for(i=0;i<30000;i++){ db.easydb.insert({"id":i,"name":"easydb.net","age":18,"date":new Date()}); }
    WriteResult({ "nInserted" : 1 })
    

    4.2 插入数据的同时备份

    [root@mysql02 ~]# mongodump -u -p --port 28018 --authenticationDatabase admin --oplog -o /tmp/backup
    2021-01-15T11:46:14.449+0800	writing admin.system.version to 
    2021-01-15T11:46:14.451+0800	done dumping admin.system.version (1 document)
    2021-01-15T11:46:14.452+0800	writing test.easydb to 
    2021-01-15T11:46:15.799+0800	done dumping test.easydb (20154 documents)
    2021-01-15T11:46:15.805+0800	writing captured oplog to 
    2021-01-15T11:46:15.991+0800		dumped 1601 oplog entries
    

    4.3 备份完成后模拟一个错误的操作

    easydb:PRIMARY> use test
    switched to db test
    
    easydb:PRIMARY> show collections
    easydb
    
    easydb:PRIMARY> db.dropDatabase()
    {
    	"dropped" : "test",
    	"ok" : 1,
    	"operationTime" : Timestamp(1610682482, 2),
    	"$clusterTime" : {
    		"clusterTime" : Timestamp(1610682482, 2),
    		"signature" : {
    			"hash" : BinData(0,"AAAAAAAAAAAAAAAAAAAAAAAAAAA="),
    			"keyId" : NumberLong(0)
    		}
    	}
    }
    

    4.4 切割全备里的oplog,找出上次全备最后一个时间的数据

    [root@mysql02 ~]# bsondump /tmp/backup/oplog.bson > /tmp/oplog.json
    2021-01-16T17:28:56.252+0800	417 objects found
    [root@mysql02 ~]# tail -1 /tmp/oplog.json 
    {"ts":{"$timestamp":{"t":1610789118,"i":416}},"t":{"$numberLong":"6"},"h":{"$numberLong":"8277197316656995929"},"v":2,"op":"i","ns":"test.easydb","ui":{"$binary":"JEUrQxOWS6Gw8vfPIetrqQ==","$type":"04"},"wall":{"$date":"2021-01-16T09:25:18.435Z"},"o":{"_id":{"$oid":"6002b0fe4994bdfbd2b0747e"},"id":17511.0,"name":"easydb.net","age":18.0,"date":{"$date":"2021-01-16T09:25:18.443Z"}}}
    
    {"t":1610789118,"i":416}就是上一次全备最后的时间戳
    

    4.5 导出上一次全备以后的增量数据

     mongodump -u -p --port 28018 --authenticationDatabase admin -d local -c oplog.rs -q '{ts:{$gt:Timestamp(1610789118,416)}}' -o /tmp/oplog
     
     #这里填的是我们上一步截取的时间戳
    

    4.6 恢复最近一次全备的数据

    mongorestore -u -p --port 28018 --authenticationDatabase admin --oplogReplay  /tmp/backup
    
    easydb:PRIMARY> use test
    switched to db test
    easydb:PRIMARY> db.easydb.count()
    17512
    
    检查全备恢复了多少条数据
    

    4.7 截取备份出来增量的oplog,找到误删库的时间点(limt)

    • 删库语句的上一个oplog时间戳为终点。
    [root@mysql02 ~]# bsondump /tmp/oplog/local/oplog.rs.bson | grep -C 5 dropDatabase
    {"ts":{"$timestamp":{"t":1610789163,"i":1}},"t":{"$numberLong":"6"},"h":{"$numberLong":"-8852159408511820267"},"v":2,"op":"n","ns":"","wall":{"$date":"2021-01-16T09:26:03.551Z"},"o":{"msg":"periodic noop"}}
    {"ts":{"$timestamp":{"t":1610789168,"i":1}},"t":{"$numberLong":"6"},"h":{"$numberLong":"-8231808943143165392"},"v":2,"op":"c","ns":"test.$cmd","ui":{"$binary":"JEUrQxOWS6Gw8vfPIetrqQ==","$type":"04"},"wall":{"$date":"2021-01-16T09:26:08.735Z"},"o":{"drop":"easydb"}}
    2021-01-16T17:51:45.426+0800	12587 objects found
    {"ts":{"$timestamp":{"t":1610789168,"i":2}},"t":{"$numberLong":"6"},"h":{"$numberLong":"-1802663680461751854"},"v":2,"op":"c","ns":"test.$cmd","wall":{"$date":"2021-01-16T09:26:08.807Z"},"o":{"dropDatabase":1}}
    {"ts":{"$timestamp":{"t":1610789183,"i":1}},"t":{"$numberLong":"6"},"h":{"$numberLong":"7216379125886047426"},"v":2,"op":"n","ns":"","wall":{"$date":"2021-01-16T09:26:23.551Z"},"o":{"msg":"periodic noop"}}
    
    {"t":1610789168,"i":1}

    将过滤出来的Unix时间戳进行转换,再次确认是不是误操作的时间点

    4.8 复制增量的oplog到备份目录,重命名为oplog.bson,将原来的oplog.bson覆盖

    cp /tmp/oplog/local/oplog.rs.bson /tmp/backup/oplog.bson
    

    4.9 将增量的oplog进行恢复,添加之前找到的误删除的点(limt)

    mongorestore -u -p --port 28018 --authenticationDatabase admin --oplogReplay --oplogLimit "1610789168:1"  /tmp/backup
    
    easydb:PRIMARY> db.easydb.count()
    30000
    再次检查,发现30000条数据已经全部恢复
    

    4.10 把恢复后的数据再做一次全备,至此一次恢复就完成了

    因为有悔,所以披星戴月;因为有梦,所以奋不顾身! 个人博客首发:easydb.net 微信公众号:easydb 关注我,不走丢!

    因为有悔,所以披星戴月;因为有梦,所以奋不顾身! 个人博客首发:easydb.net 微信公众号:easydb 关注我,不走丢!
  • 相关阅读:
    优秀IT技术文章集(最新)(高质量)
    大型网站系统架构演化之路
    一起学Maven
    Drupal8 新建第一个模块
    理解依赖注入(Dependency Injection)
    Yii2 模块module笔记
    Drupal views 学习之筛选器
    Drupal views 学习之初识
    Drupal views 中合并显示字段
    解读python手册的例子a, b = b, a+b
  • 原文地址:https://www.cnblogs.com/easydb/p/14286810.html
Copyright © 2011-2022 走看看