跳到主要内容

备份与恢复

数据备份是数据库运维中最关键的任务之一。本章介绍 MongoDB 的各种备份和恢复策略,帮助你保护数据安全。

为什么需要备份?

数据丢失可能由多种原因造成:

备份策略原则

  • 3-2-1 原则:至少保留 3 份备份,存储在 2 种不同的介质上,其中 1 份存放在异地
  • 定期测试:定期验证备份是否可以正常恢复
  • 自动化:使用脚本或工具自动化备份流程

备份方式对比

方式适用场景优点缺点
mongodump/mongorestore小型数据库、开发环境简单易用、跨版本兼容大数据量慢、影响性能
文件系统快照大型数据库、生产环境速度快、影响小需要文件系统支持
MongoDB Atlas 备份云端部署自动化、可恢复到任意时间点仅适用于 Atlas
副本集延迟节点高可用环境实时备份、可快速恢复需要额外资源

mongodump 与 mongorestore

mongodumpmongorestore 是 MongoDB 自带的逻辑备份工具,适合中小型数据库。

mongodump - 导出数据

基本用法

# 导出所有数据库
mongodump --host localhost --port 27017 --out /backup/$(date +%Y%m%d)

# 导出指定数据库
mongodump --host localhost --port 27017 --db myapp --out /backup/$(date +%Y%m%d)

# 导出指定集合
mongodump --host localhost --port 27017 --db myapp --collection users --out /backup/$(date +%Y%m%d)

# 使用 URI 连接
mongodump --uri="mongodb://user:password@localhost:27017/myapp" --out /backup/$(date +%Y%m%d)

常用参数

参数说明示例
--hostMongoDB 主机--host localhost
--portMongoDB 端口--port 27017
--db指定数据库--db myapp
--collection指定集合--collection users
--out输出目录--out /backup
--query导出符合条件的文档--query '{"status":"active"}'
--gzip压缩输出--gzip
--archive输出到单个归档文件--archive=backup.archive
--oplog记录备份期间的 oplog(用于时间点恢复)--oplog

进阶用法

# 压缩备份
mongodump --host localhost --db myapp --gzip --out /backup/$(date +%Y%m%d)

# 输出到单个归档文件
mongodump --host localhost --db myapp --archive=/backup/myapp.archive --gzip

# 带条件导出(只导出活跃用户)
mongodump --host localhost --db myapp --collection users --query '{"status":"active"}'

# 副本集备份(带 oplog,用于时间点恢复)
mongodump --host rs0/localhost:27017,localhost:27018 --oplog --out /backup/$(date +%Y%m%d)

mongorestore - 恢复数据

基本用法

# 恢复所有数据库
mongorestore --host localhost --port 27017 /backup/20240115

# 恢复指定数据库
mongorestore --host localhost --port 27017 --db myapp /backup/20240115/myapp

# 恢复指定集合
mongorestore --host localhost --port 27017 --db myapp --collection users /backup/20240115/myapp/users.bson

# 从归档文件恢复
mongorestore --host localhost --archive=/backup/myapp.archive --gzip

常用参数

参数说明示例
--drop恢复前删除现有集合--drop
--gzip解压 gzip 压缩的备份--gzip
--archive从归档文件恢复--archive=backup.archive
--oplogReplay重放 oplog(时间点恢复)--oplogReplay
--stopOnError遇到错误时停止--stopOnError
--noIndexRestore不恢复索引--noIndexRestore

进阶用法

# 恢复并删除现有数据
mongorestore --host localhost --db myapp --drop /backup/20240115/myapp

# 时间点恢复(需要备份时使用了 --oplog)
mongorestore --host localhost --oplogReplay /backup/20240115

# 只恢复数据,不恢复索引(加快恢复速度)
mongorestore --host localhost --db myapp --noIndexRestore /backup/20240115/myapp

# 恢复后重建索引
mongorestore --host localhost --db myapp /backup/20240115/myapp

文件系统快照

文件系统快照是物理备份方式,适合大型生产环境。

工作原理

使用 LVM 快照

# 1. 锁定 MongoDB(在 mongosh 中执行)
db.fsyncLock()

# 2. 创建 LVM 快照
lvcreate --size 10G --snapshot --name mongodb_snap /dev/vg0/mongodb

# 3. 解锁 MongoDB
db.fsyncUnlock()

# 4. 挂载快照进行备份
mkdir /mnt/mongodb_snap
mount /dev/vg0/mongodb_snap /mnt/mongodb_snap

# 5. 复制数据到备份位置
rsync -avz /mnt/mongodb_snap/ /backup/mongodb_$(date +%Y%m%d)/

# 6. 卸载并删除快照
umount /mnt/mongodb_snap
lvremove /dev/vg0/mongodb_snap

使用云服务商快照

# AWS EBS 快照(示例)
aws ec2 create-snapshot --volume-id vol-123456 --description "MongoDB backup"

# 阿里云快照(示例)
aliyun ecs CreateSnapshot --DiskId d-123456 --SnapshotName mongodb_backup

mongoexport 与 mongoimport

用于导出和导入 JSON 或 CSV 格式数据,适合数据迁移和部分数据导出。

mongoexport - 导出数据

# 导出为 JSON 格式
mongoexport --host localhost --db myapp --collection users --out users.json

# 导出为 CSV 格式
mongoexport --host localhost --db myapp --collection users --type=csv --fields name,email,age --out users.csv

# 导出符合条件的文档
mongoexport --host localhost --db myapp --collection users --query '{"status":"active"}' --out active_users.json

# 格式化 JSON 输出
mongoexport --host localhost --db myapp --collection users --pretty --out users_pretty.json

mongoimport - 导入数据

# 导入 JSON 文件
mongoimport --host localhost --db myapp --collection users --file users.json

# 导入 CSV 文件
mongoimport --host localhost --db myapp --collection users --type=csv --headerline --file users.csv

# 导入时忽略重复键
mongoimport --host localhost --db myapp --collection users --file users.json --mode=merge

# 导入时更新已存在的文档
mongoimport --host localhost --db myapp --collection users --file users.json --mode=upsert --upsertFields email

副本集延迟节点

通过配置延迟副本节点,实现"热备份"。

配置延迟节点

// 查看当前副本集配置
rs.conf()

// 设置延迟节点(延迟 1 小时)
var config = rs.conf()
config.members[2].priority = 0 // 不参与选举
config.members[2].hidden = true // 隐藏节点
config.members[2].slaveDelay = 3600 // 延迟 3600 秒
rs.reconfig(config)

// 验证配置
rs.conf()

从延迟节点恢复

// 1. 停止延迟节点
db.adminCommand({ shutdown: 1 })

// 2. 复制数据文件到新位置作为备份
// cp -r /data/db /backup/

// 3. 重启节点
// mongod --replSet rs0 --dbpath /data/db

MongoDB Atlas 云备份

如果使用 MongoDB Atlas,可以利用其自动备份功能。

自动备份

Atlas 提供以下备份选项:

  1. Cloud Backup:基于快照的备份

    • 支持时间点恢复
    • 可设置保留策略
    • 支持跨区域复制
  2. Continuous Cloud Backup:连续备份

    • 可恢复到任意时间点(最近 24-72 小时)
    • 增量备份,节省空间

备份操作

# 通过 Atlas CLI 创建备份快照
atlas backups snapshots create <clusterName> --desc "Manual backup"

# 恢复快照
atlas backups restores start <clusterName> --snapshotId <snapshotId>

备份脚本示例

完整备份脚本

#!/bin/bash
# MongoDB 自动备份脚本

# 配置
MONGO_HOST="localhost"
MONGO_PORT="27017"
MONGO_USER="backup_user"
MONGO_PASS="backup_password"
BACKUP_DIR="/backup/mongodb"
DAYS_TO_KEEP=7

# 创建备份目录
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_PATH="${BACKUP_DIR}/${DATE}"
mkdir -p ${BACKUP_PATH}

# 执行备份
echo "开始备份: ${DATE}"
mongodump \
--host ${MONGO_HOST} \
--port ${MONGO_PORT} \
--username ${MONGO_USER} \
--password ${MONGO_PASS} \
--authenticationDatabase admin \
--gzip \
--out ${BACKUP_PATH}

# 检查备份是否成功
if [ $? -eq 0 ]; then
echo "备份成功: ${BACKUP_PATH}"

# 发送成功通知
# curl -X POST "webhook_url" -d "MongoDB备份成功"
else
echo "备份失败!"

# 发送失败通知
# curl -X POST "webhook_url" -d "MongoDB备份失败"
exit 1
fi

# 清理旧备份
find ${BACKUP_DIR} -type d -mtime +${DAYS_TO_KEEP} -exec rm -rf {} \;
echo "清理完成,保留最近 ${DAYS_TO_KEEP} 天的备份"

定时备份(Crontab)

# 编辑 crontab
crontab -e

# 每天凌晨 2 点执行备份
0 2 * * * /path/to/backup_script.sh >> /var/log/mongodb_backup.log 2>&1

# 每周日凌晨 3 点执行完整备份
0 3 * * 0 /path/to/backup_script.sh >> /var/log/mongodb_backup.log 2>&1

备份恢复最佳实践

1. 备份前检查

# 检查磁盘空间
df -h /backup

# 检查 MongoDB 状态
mongosh --eval "rs.status()"

# 检查数据大小
mongosh --eval "db.stats()"

2. 验证备份有效性

# 定期测试恢复流程
# 1. 恢复到测试环境
mongorestore --host test-mongo --port 27017 --drop /backup/20240115/myapp

# 2. 验证数据完整性
mongosh test-mongo --eval "db.users.countDocuments()"

# 3. 检查索引
mongosh test-mongo --eval "db.users.getIndexes()"

3. 监控备份状态

# 检查备份文件大小
du -sh /backup/mongodb/*

# 检查备份文件完整性
ls -la /backup/mongodb/$(date +%Y%m%d)/*

# 监控备份日志
tail -f /var/log/mongodb_backup.log

4. 制定恢复计划

场景恢复方法预计时间
误删单条记录从备份恢复特定文档分钟级
误删集合mongorestore 恢复集合分钟到小时
数据库损坏完整恢复小时级
灾难恢复异地备份恢复数小时

常见问题

1. 备份过程中数据库会被锁住吗?

mongodump:不会锁住数据库,但会增加系统负载。建议在低峰期执行。

文件系统快照:需要短暂锁定(fsyncLock),通常只需几秒。

2. 如何备份大型数据库?

# 方法1:并行备份多个集合
mongodump --host localhost --db myapp --collection users --out /backup &
mongodump --host localhost --db myapp --collection orders --out /backup &
wait

# 方法2:使用文件系统快照
# 见上文文件系统快照部分

# 方法3:从副本集从节点备份
mongodump --host secondary1:27017 --db myapp --out /backup

3. 如何实现时间点恢复?

# 备份时记录 oplog
mongodump --host localhost --oplog --out /backup/$(date +%Y%m%d)

# 恢复时重放 oplog
mongorestore --host localhost --oplogReplay /backup/20240115

小结

本章我们学习了:

  1. 备份策略:3-2-1 原则和备份规划
  2. mongodump/mongorestore:逻辑备份工具的使用
  3. 文件系统快照:物理备份方式
  4. mongoexport/mongoimport:JSON/CSV 格式导出导入
  5. 延迟节点:热备份方案
  6. Atlas 云备份:云端自动备份
  7. 备份脚本:自动化备份实践
  8. 最佳实践:验证、监控、恢复计划

备份是数据安全的最后一道防线,请务必重视并定期验证备份的有效性。