# Mongodb增量备份和基于时间点恢复

> 作者/来源: UCloud 运营管理员
> 发布时间: 2023-01-11T05:20:00.000Z
> 分类: 解决方案
> 标签: 数据库, 存储
> 原文链接: http://117.50.162.249:3000/yun/articles/896

---

# Mongodb增量备份和基于时间点恢复

> 来源: https://www.ucloud.cn/yun/129954.html
> 作者: IT那活儿
> 发布日期: 发布于2023-01-11 13:20

Mongodb增量备份和基于时间点恢复

数据库备份是DBA的一种日常工作，备份包括物理备份和逻辑备份。每一种DBMS产品都提供了自己的备份和恢复的工具，如Oracle的rman和数据泵就是实现数据库备份工具的代表。

要实现数据库增量备份一般都是基于物理备份备份来实现，如rman0级+N级+归档日志，但是Mongodb官方以及第三方都没有提供物理备份工具（基于文件系统的除外），仅提供了用于逻辑备份的mongoexport或者Mongodump。一般来说逻辑备份是无法实现增量的，但在Mongodb复制集中，提供了一个名为oplog的固定大小集合（默认为磁盘空间的5%，可手动修改）来存储所有的数据变更操作（复制集架构就利用此集合来进行数据同步），并且其具有幂等性的特点，因此可通过备份oplog的方式来进行增量备份和增量恢复。

由于oplog的幂等性，即做了多次oplog恢复或者多次重复的操作，也能保证其数据跟只执行一次的结果相同，所以我们使用如下方案来实现增量备份和恢复：

**1、全备：**按固定频率进行mongodump全库导出备份，如每天一次

**2、增量备份：**按固定频率使用Mongodump进行oplog备份，且每次备份时指定备份的起始位置为上次备份时间的前面几分钟，即多备份几分钟的oplog数据，这样可确保数据不丢失。此处要注意，oplog是一个capped集合，所以备份周期必须在oplog保留的时间范围内（即按照当前数据库的oplog大小，假如oplog集合可以保存3小时的数据，那么备份频率不能高于3小时）。例：每小时备份一次oplog

|  |
| --- |
| starttime=`date-d -62 Minutes +%s`  mongodump--host=127.0.0.1 --port=27017 --authenticationDatabase admin -uroot-p\*\*\* -d local -c oplog.rs --gzip --query{ts:{$gte:Timestamp($starttime, 1)}} --out=/backupdir  在本例中，每小时备份一次oplog，每次备份的起始时间点为当前时间的前面62min,这样每次重复备份2min的oplog。 |

若出现了故障导致数据丢失或者人为误操作，可以将数据恢复到任意时间点

**3、全库恢复：**利用步骤1的全备进行恢复。

**4、指定从全备开始前的上一个oplog备份集开始进行恢复，一直恢复到指定的时间点。**例：多次恢复oplog直到指定的时间点。

mongorestore-h 127.0.0.1 --port 27017 --oplogReplay  /backup/oplog2021032714

mongorestore-h 127.0.0.1 --port 27017 --oplogReplay  /backup/oplog2021032715

…………

mongorestore-h 127.0.0.1 --port 27017 --oplogReplay --oplogLimit  /backup/oplog/oplog.rs.bson

需要注意的是，oplog只存在于复制集架构中，单机数据库是不会写oplog的，所以针对单机架构，如果要实现增量备份的话，若有多的机器，可改成复制集，如果没有多余的机器，则可将单机改成单节点的复制集。对于分片集群架构，要求将所有分片部署成复制集架构，备份需基于所有的分片进行备份，而不能基于mongos进行备份。

**附：增量备份脚本：**

|  |
| --- |
| #!/bin/bash  ##env set  mongobin="/usr/local/mongodb/bin"  host=localhost  mongouser="admin"  mongopwd="123456"  mongoport=27017    fullbakdir=/home/mongo/backup/full-`date+%F`  inc\_bakdir=/home/mongo/backup/inc-`date+"%Y-%m-%d-%H%M%S"`    #starttime=`date-d -1 hours +%s`  starttime=`date-d -62 Minutes +%s`    checktime=3900    ##Make needs dirs  functionfulldir()  {  if[ ! -d "${fullbakdir}" ]; then  mkdir-p ${fullbakdir}  else  echo"已经存在备份目录,本次备份退出,请检查环境"  exit  fi  }    functionincdir()  {  if[ ! -d "${inc\_bakdir}" ]; then  mkdir-p ${inc\_bakdir}  fi  }    functionfullback()  {  ${mongobin}/mongodump--host=${host} --port=${mongoport} --authenticationDatabase admin-u${mongouser} -p${mongopwd} -j 8 --oplog --gzip --out=${fullbakdir}  }    functioninclback()  {  ${mongobin}/mongodump--host=${host} --port=${mongoport} --authenticationDatabase admin-u${mongouser} -p${mongopwd} -d local -c oplog.rs --gzip --query{ts:{$gte:Timestamp($starttime, 1)}} --out=${inc\_bakdir}  }      functionchkoplog()  {  oplogtime=`mongo--eval "rs.printReplicationInfo()" |grep "log lengthstart to end" |awk {print $6} |awk -Fs {print $1}`  echo$oplogtime  if[ ${oplogtime} -gt 60 ];then  return0  else  return1  fi  }      signal=${1:-full}    if[ ${signal} = full ];then  fulldir  fullback  elif[ ${signal} = inc ];then  incdir  chkoplog  if[ $? -eq 0 ];then  inclback  else  echo"send msg"  fi  else  echo"请指定备份类型"  fi |

通过在crontab中部署定时任务来实现固定频率备份

13 \* \* \* sh /home/mongo/scripts/backup.sh full

30\*/1 \* \* \* sh /home/mongo/scripts/backup.sh inc

![](https://ucloud-blog.cn-bj.ufileos.com/articles/129954/images/129954_000.png)

END

![](https://ucloud-blog.cn-bj.ufileos.com/articles/129954/images/129954_001.png)