MongoDB 备份与恢复:mongodump 和 mongorestore 实战
第一章:MongoDB 备份恢复概述
1.1 数据备份的重要性
在当今数据驱动的时代,数据是企业最宝贵的资产之一。MongoDB 作为最流行的 NoSQL 数据库,承载着大量关键业务数据。数据备份的重要性体现在:
业务连续性保障:
- 防止数据丢失导致业务中断
- 满足合规性和监管要求
- 支持灾难恢复计划
数据管理需求: - 环境迁移和数据同步
- 版本控制和变更回滚
- 测试数据准备和开发支持
1.2 MongoDB 备份策略类型
备份类型 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
逻辑备份 (mongodump) | 跨版本兼容、可选择性备份、体积小 | 备份恢复慢、需要停机时间 | 开发测试、小规模数据 |
物理备份 (文件系统快照) | 备份恢复快、几乎无需停机 | 存储需求大、版本依赖强 | 生产环境、大规模数据 |
持续备份 (oplog) | 实时保护、秒级RPO | 配置复杂、资源消耗大 | 关键业务、零数据丢失要求 |
1.3 备份架构示意图
[应用程序] → [MongoDB 主节点] → [备份服务器]
│ │ │
│ ↓ ↓
└──────→ [监控系统] [云存储/磁带库]
第二章:mongodump 工具详解
2.1 mongodump 基本语法
mongodump --uri="mongodb://用户名:密码@主机:端口/数据库" \
--collection=集合名 \
--out=备份目录 \
--gzip \
--query='{"字段": {"$gt": 100}}'
2.2 常用参数详解
连接参数:
- –uri:连接字符串(MongoDB 4.4+)
- –host:主机地址
- –port:端口号
- –username:用户名
- –password:密码
- –authenticationDatabase:认证数据库
备份参数: - –db:指定数据库
- –collection:指定集合
- –out:输出目录
- –gzip:压缩备份
- –query:过滤条件
- –excludeCollection:排除集合
2.3 实战示例:完整备份
#!/bin/bash
# 完整数据库备份脚本
BACKUP_DIR="/data/backup/mongodb"
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOG_FILE="/var/log/mongodb/backup_${TIMESTAMP}.log"
# 创建备份目录
mkdir -p ${BACKUP_DIR}/${TIMESTAMP}
# 执行备份
mongodump \
--host="localhost:27017" \
--username="admin" \
--password="securepassword" \
--authenticationDatabase="admin" \
--out="${BACKUP_DIR}/${TIMESTAMP}" \
--gzip \
--verbose 2>&1 | tee ${LOG_FILE}
# 验证备份完整性
if [ $? -eq 0 ]; then
echo "备份成功完成: ${TIMESTAMP}"
# 清理旧备份(保留最近7天)
find ${BACKUP_DIR} -type d -mtime +7 -exec rm -rf {} \;
else
echo "备份失败,请检查日志: ${LOG_FILE}"
exit 1
fi
2.4 实战示例:增量备份
#!/bin/bash
# 基于查询的增量备份
LAST_BACKUP_TIME="20240101_000000"
CURRENT_TIME=$(date +%Y%m%d_%H%M%S)
mongodump \
--uri="mongodb://admin:password@localhost:27017/mydb" \
--query="{\"timestamp\": {\"\$gt\": {\"\$date\": \"${LAST_BACKUP_TIME}\"}}}" \
--out="/backups/incremental_${CURRENT_TIME}" \
--gzip
2.5 备份文件结构解析
backup_20240101/
├── admin/
│ ├── system.users.bson.gz
│ └── system.users.metadata.json.gz
├── mydb/
│ ├── collection1.bson.gz
│ ├── collection1.metadata.json.gz
│ ├── collection2.bson.gz
│ └── collection2.metadata.json.gz
└── backup.log
第三章:mongorestore 工具详解
3.1 mongorestore 基本语法
mongorestore --uri="mongodb://用户名:密码@主机:端口/数据库" \
--dir=备份目录 \
--gzip \
--drop \
--nsInclude="数据库.集合"
3.2 常用参数详解
恢复参数:
- –dir:备份文件目录
- –gzip:解压缩恢复
- –drop:恢复前删除集合
- –nsInclude:包含的命名空间
- –nsExclude:排除的命名空间
- –noIndexRestore:不恢复索引
3.3 实战示例:完整恢复
#!/bin/bash
# 完整数据库恢复脚本
BACKUP_DIR="/data/backup/mongodb/20240101_120000"
TARGET_URI="mongodb://admin:password@localhost:27017"
mongorestore \
--uri="${TARGET_URI}" \
--dir="${BACKUP_DIR}" \
--gzip \
--drop \
--verbose
if [ $? -eq 0 ]; then
echo "恢复成功完成"
else
echo "恢复失败"
exit 1
fi
3.4 实战示例:部分恢复
# 恢复特定集合
mongorestore \
--uri="mongodb://localhost:27017" \
--nsInclude="mydb.important_collection" \
--dir="/backups/full_backup" \
--gzip
# 恢复时重命名集合
mongorestore \
--uri="mongodb://localhost:27017" \
--nsFrom="mydb.old_collection" \
--nsTo="mydb.new_collection" \
--dir="/backups/full_backup" \
--gzip
第四章:高级备份策略
4.1 分片集群备份
#!/bin/bash
# 分片集群备份脚本
CONFIG_SERVER="cfg1.example.com:27019"
SHARDS=("shard1.example.com:27018" "shard2.example.com:27018")
# 备份配置服务器
mongodump --host=${CONFIG_SERVER} --out=/backups/config_server --gzip
# 备份每个分片
for shard in "${SHARDS[@]}"; do
shard_name=$(echo ${shard} | cut -d':' -f1)
mongodump --host=${shard} --out="/backups/shards/${shard_name}" --gzip
done
4.2 副本集备份
#!/bin/bash
# 从副本集次要节点备份
SECONDARY_NODE="secondary.example.com:27017"
# 检查节点状态
Node_state=$(mongo --host ${SECONDARY_NODE} --eval "rs.status().members.find(m => m.name == '${SECONDARY_NODE}').stateStr" --quiet)
if [ "${Node_state}" == "SECONDARY" ]; then
mongodump --host=${SECONDARY_NODE} --out=/backups/secondary_backup --gzip
else
echo "节点不是次要节点,无法备份"
exit 1
fi
4.3 加密备份
# 使用OpenSSL加密备份文件
mongodump --uri="mongodb://localhost:27017/mydb" --out=- --gzip | \
openssl enc -aes-256-cbc -salt -out /backups/encrypted_backup.enc -pass pass:mysecret
# 解密并恢复
openssl enc -d -aes-256-cbc -in /backups/encrypted_backup.enc -pass pass:mysecret | \
mongorestore --uri="mongodb://localhost:27017/mydb" --gzip -
第五章:备份恢复实战场景
5.1 生产环境备份方案
多级备份策略:
#!/bin/bash
# 多级备份策略:每日+每周+每月
BACKUP_ROOT="/data/backup/mongodb"
DATE=$(date +%Y%m%d)
DAY=$(date +%d)
WEEKDAY=$(date +%w)
# 每日备份
mongodump --uri="mongodb://localhost:27017" --out="${BACKUP_ROOT}/daily/${DATE}" --gzip
# 周日执行每周备份
if [ ${WEEKDAY} -eq 0 ]; then
cp -r "${BACKUP_ROOT}/daily/${DATE}" "${BACKUP_ROOT}/weekly/${DATE}"
fi
# 每月1号执行月度备份
if [ ${DAY} -eq 1 ]; then
cp -r "${BACKUP_ROOT}/daily/${DATE}" "${BACKUP_ROOT}/monthly/${DATE}"
fi
# 清理策略
find "${BACKUP_ROOT}/daily" -type d -mtime +7 -exec rm -rf {} \;
find "${BACKUP_ROOT}/weekly" -type d -mtime +30 -exec rm -rf {} \;
find "${BACKUP_ROOT}/monthly" -type d -mtime +365 -exec rm -rf {} \;
5.2 跨版本迁移实战
# 从MongoDB 4.4备份
mongodump --host=old_server:27017 --out=/backups/mongo44_backup
# 恢复到MongoDB 6.0
mongorestore --host=new_server:27017 --dir=/backups/mongo44_backup
# 验证数据一致性
mongo --host=new_server:27017 --eval "
db.adminCommand({listDatabases:1});
db.stats();
"
5.3 大数据量备份优化
# 并行备份多个集合
COLLECTIONS=("collection1" "collection2" "collection3")
for collection in "${COLLECTIONS[@]}"; do
mongodump \
--uri="mongodb://localhost:27017/mydb" \
--collection="${collection}" \
--out="/backups/parallel_${collection}" \
--gzip &
done
wait
echo "所有集合备份完成"
第六章:监控与验证
6.1 备份监控脚本
#!/bin/bash
# 备份监控和告警脚本
BACKUP_DIR="/data/backup/mongodb"
MIN_SIZE=1000000 # 最小备份大小1GB
ALERT_EMAIL="admin@example.com"
# 检查最新备份
LATEST_BACKUP=$(ls -t ${BACKUP_DIR} | head -1)
BACKUP_SIZE=$(du -s "${BACKUP_DIR}/${LATEST_BACKUP}" | cut -f1)
# 检查备份完整性
if [ ${BACKUP_SIZE} -lt ${MIN_SIZE} ]; then
echo "警告: 备份大小异常 ${BACKUP_SIZE}" | mail -s "MongoDB备份异常" ${ALERT_EMAIL}
fi
# 检查备份时间(不超过24小时)
BACKUP_AGE=$(find "${BACKUP_DIR}/${LATEST_BACKUP}" -type f -name "*.bson.gz" -exec stat -c %Y {} \; | sort -n | tail -1)
CURRENT_TIME=$(date +%s)
AGE_HOURS=$(( (CURRENT_TIME - BACKUP_AGE) / 3600 ))
if [ ${AGE_HOURS} -gt 24 ]; then
echo "警告: 备份已过期 ${AGE_HOURS}小时" | mail -s "MongoDB备份过期" ${ALERT_EMAIL}
fi
6.2 数据一致性验证
// 数据一致性验证脚本
db = db.getSiblingDB('mydb');
// 检查文档数量
var originalCount = db.original_collection.countDocuments();
var restoredCount = db.restored_collection.countDocuments();
print("原始集合文档数: " + originalCount);
print("恢复集合文档数: " + restoredCount);
// 抽样验证数据完整性
var sampleDocs = db.original_collection.aggregate([{ $sample: { size: 100 } }]).toArray();
sampleDocs.forEach(function(doc) {
var restoredDoc = db.restored_collection.findOne({ _id: doc._id });
if (!restoredDoc) {
print("警告: 文档丢失: " + doc._id);
} else if (JSON.stringify(doc) !== JSON.stringify(restoredDoc)) {
print("警告: 文档不匹配: " + doc._id);
}
});
print("数据验证完成");
第七章:故障排除与优化
7.1 常见问题解决
内存不足错误:
# 调整mongodump内存使用
mongodump --uri="mongodb://localhost:27017" \
--out="/backups" \
--batchSize=100 \
--numParallelCollections=2
网络超时问题:
# 增加超时时间
mongodump --host=remote_server:27017 \
--username=admin \
--password=password \
--out="/backups" \
--gzip \
--networkTimeout=300000 # 5分钟超时
7.2 性能优化技巧
并行处理优化:
# 使用并行处理加速备份
mongodump --uri="mongodb://localhost:27017" \
--out="/backups" \
--numParallelCollections=4 \
--writeConcern="{w:0}" # 不等待确认
IO优化:
# 使用更快的存储设备
mongodump --uri="mongodb://localhost:27017" \
--out="/ssd_backups" # SSD存储
第八章:自动化与集成
8.1 完整自动化方案
#!/bin/bash
# 完整的自动化备份解决方案
set -e # 遇到错误立即退出
# 配置参数
MONGODB_URI="mongodb://admin:password@localhost:27017"
BACKUP_DIR="/data/backup/mongodb"
RETENTION_DAYS=7
LOG_DIR="/var/log/mongodb"
# 创建目录
mkdir -p ${BACKUP_DIR}
mkdir -p ${LOG_DIR}
# 生成时间戳
TIMESTAMP=$(date +%Y%m%d_%H%M%S)
LOG_FILE="${LOG_DIR}/backup_${TIMESTAMP}.log"
# 执行备份
echo "开始MongoDB备份: ${TIMESTAMP}" | tee -a ${LOG_FILE}
mongodump --uri="${MONGODB_URI}" \
--out="${BACKUP_DIR}/${TIMESTAMP}" \
--gzip \
--verbose 2>&1 | tee -a ${LOG_FILE}
# 检查备份结果
if [ $? -eq 0 ]; then
BACKUP_SIZE=$(du -sh "${BACKUP_DIR}/${TIMESTAMP}" | cut -f1)
echo "备份成功: ${BACKUP_SIZE}" | tee -a ${LOG_FILE}
# 清理旧备份
find ${BACKUP_DIR} -type d -mtime +${RETENTION_DAYS} -exec rm -rf {} \; 2>/dev/null || true
else
echo "备份失败" | tee -a ${LOG_FILE}
exit 1
fi
echo "备份流程完成: $(date)" | tee -a ${LOG_FILE}
8.2 与监控系统集成
#!/bin/bash
# 与Prometheus监控系统集成
BACKUP_DIR="/data/backup/mongodb"
METRICS_FILE="/tmp/mongodb_backup_metrics.prom"
# 生成监控指标
echo "# HELP mongodb_backup_size_bytes MongoDB备份大小字节数" > ${METRICS_FILE}
echo "# TYPE mongodb_backup_size_bytes gauge" >> ${METRICS_FILE}
echo "mongodb_backup_size_bytes $(du -s ${BACKUP_DIR} | cut -f1)" >> ${METRICS_FILE}
echo "# HELP mongodb_backup_age_seconds MongoDB备份年龄秒数" >> ${METRICS_FILE}
echo "# TYPE mongodb_backup_age_seconds gauge" >> ${METRICS_FILE}
LATEST_BACKUP=$(ls -t ${BACKUP_DIR} | head -1)
if [ -n "${LATEST_BACKUP}" ]; then
BACKUP_AGE=$(stat -c %Y "${BACKUP_DIR}/${LATEST_BACKUP}")
CURRENT_TIME=$(date +%s)
echo "mongodb_backup_age_seconds $((CURRENT_TIME - BACKUP_AGE))" >> ${METRICS_FILE}
fi
# 推送到Prometheus Pushgateway
curl -X POST -H "Content-Type: text/plain" --data-binary @${METRICS_FILE} \
"http://prometheus:9091/metrics/job/mongodb_backup"
附录:实用命令参考
快速参考手册
常用mongodump命令:
# 基本备份
mongodump --host=localhost --out=/backups
# 压缩备份
mongodump --uri="mongodb://localhost:27017" --gzip --out=/backups
# 特定集合备份
mongodump --db=mydb --collection=users --out=/backups
# 带查询条件的备份
mongodump --query='{"created_at": {"$gt": {"$date": "2024-01-01T00:00:00Z"}}}' --out=/backups
常用mongorestore命令:
# 基本恢复
mongorestore --host=localhost --dir=/backups
# 压缩恢复
mongorestore --gzip --dir=/backups
# 恢复特定数据库
mongorestore --db=mydb --dir=/backups/mydb
# 恢复时删除现有数据
mongorestore --drop --dir=/backups
故障排除命令
连接测试:
# 测试数据库连接
mongo --host=localhost --username=admin --password=password --eval "db.adminCommand({ping:1})"
# 检查数据库大小
mongo --eval "db.stats()" mydb
备份验证:
# 检查备份文件完整性
bsondump --objcheck /backups/mydb/users.bson
# 查看备份元数据
zcat /backups/mydb/users.metadata.json.gz | jq .
通过本指南,您应该能够全面掌握MongoDB的备份与恢复技术,构建可靠的数据保护策略。记住,定期测试恢复流程和验证备份完整性同样重要!