Skip to content

备份与恢复

数据备份是数据库管理中最重要的工作之一。本章将介绍MongoDB的各种备份方法、恢复策略以及数据导入导出操作。

备份概述

备份类型

bash
# MongoDB备份类型:

# 1. 逻辑备份
#    使用工具导出数据(mongodump、mongoexport)
#    优点:可读性强、跨版本兼容
#    缺点:速度慢、大数据量不适用

# 2. 物理备份
#    直接复制数据文件
#    优点:速度快、适合大数据量
#    缺点:需要停止服务或使用快照

# 3. 文件系统快照
#    使用LVM、ZFS等文件系统快照
#    优点:速度快、一致性保证
#    缺点:需要特定文件系统支持

# 备份策略选择:
# - 小数据量:mongodump
# - 大数据量:文件系统快照或复制数据文件
# - 复制集:从节点备份
# - 分片集群:配置服务器和分片备份

mongodump备份

基本用法

bash
# mongodump是MongoDB自带的逻辑备份工具

# 备份所有数据库
mongodump --host localhost --port 27017 \
  --username admin --password \
  --authenticationDatabase admin \
  --out /backup/mongodb_$(date +%Y%m%d)

# 备份指定数据库
mongodump --host localhost --port 27017 \
  --db mydb \
  --out /backup/mongodb_$(date +%Y%m%d)

# 备份指定集合
mongodump --host localhost --port 27017 \
  --db mydb --collection users \
  --out /backup/mongodb_$(date +%Y%m%d)

# 使用URI连接
mongodump --uri="mongodb://admin:password@localhost:27017/mydb?authSource=admin" \
  --out /backup/mongodb_$(date +%Y%m%d)

常用选项

bash
# mongodump常用选项

# --host:MongoDB服务器地址
# --port:MongoDB服务器端口
# --username:用户名
# --password:密码
# --authenticationDatabase:认证数据库
# --db:指定数据库
# --collection:指定集合
# --query:备份符合条件的文档
# --out:输出目录
# --gzip:压缩输出
# --oplog:记录备份期间的oplog(用于时间点恢复)
# --archive:输出到单个归档文件

# 使用gzip压缩
mongodump --host localhost --port 27017 \
  --db mydb \
  --gzip \
  --out /backup/mongodb_$(date +%Y%m%d)

# 输出到单个归档文件
mongodump --host localhost --port 27017 \
  --db mydb \
  --archive=/backup/mydb_$(date +%Y%m%d).archive

# 压缩归档文件
mongodump --host localhost --port 27017 \
  --db mydb \
  --gzip \
  --archive=/backup/mydb_$(date +%Y%m%d).archive.gz

# 备份指定查询条件的数据
mongodump --host localhost --port 27017 \
  --db mydb --collection orders \
  --query '{"status": "completed"}' \
  --out /backup/mongodb_$(date +%Y%m%d)

# 使用oplog备份(用于时间点恢复)
mongodump --host localhost --port 27017 \
  --oplog \
  --out /backup/mongodb_$(date +%Y%m%d)

复制集备份

bash
# 从复制集备份(从从节点备份,减少主节点压力)

# 指定从节点备份
mongodump --host secondary1.example.com --port 27017 \
  --db mydb \
  --out /backup/mongodb_$(date +%Y%m%d)

# 使用readPreference
mongodump --host rs0/primary.example.com,secondary1.example.com \
  --readPreference=secondary \
  --db mydb \
  --out /backup/mongodb_$(date +%Y%m%d)

# 完整备份(包含oplog)
mongodump --host rs0/primary.example.com,secondary1.example.com \
  --oplog \
  --gzip \
  --archive=/backup/mongodb_full_$(date +%Y%m%d).archive.gz

mongorestore恢复

基本用法

bash
# mongorestore是MongoDB的数据恢复工具

# 恢复所有数据库
mongorestore --host localhost --port 27017 \
  --username admin --password \
  --authenticationDatabase admin \
  /backup/mongodb_20240101

# 恢复指定数据库
mongorestore --host localhost --port 27017 \
  --db mydb \
  /backup/mongodb_20240101/mydb

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

# 从归档文件恢复
mongorestore --host localhost --port 27017 \
  --archive=/backup/mydb_20240101.archive

# 从压缩归档文件恢复
mongorestore --host localhost --port 27017 \
  --gzip \
  --archive=/backup/mydb_20240101.archive.gz

恢复选项

bash
# mongorestore常用选项

# --drop:恢复前删除现有数据
mongorestore --host localhost --port 27017 \
  --drop \
  /backup/mongodb_20240101

# --nsInclude:只恢复匹配的命名空间
mongorestore --host localhost --port 27017 \
  --nsInclude="mydb.*" \
  /backup/mongodb_20240101

# --nsExclude:排除匹配的命名空间
mongorestore --host localhost --port 27017 \
  --nsExclude="mydb.logs.*" \
  /backup/mongodb_20240101

# --nsFrom 和 --nsTo:重命名命名空间
mongorestore --host localhost --port 27017 \
  --nsFrom="mydb.*" \
  --nsTo="mydb_restored.*" \
  /backup/mongodb_20240101

# 恢复oplog(时间点恢复)
mongorestore --host localhost --port 27017 \
  --oplogReplay \
  /backup/mongodb_20240101

# 停止应用oplog的时间点
mongorestore --host localhost --port 27017 \
  --oplogReplay \
  --oplogLimit "2024-01-01 12:00:00" \
  /backup/mongodb_20240101

数据导入导出

mongoexport导出

bash
# mongoexport:将数据导出为JSON或CSV格式

# 导出为JSON格式
mongoexport --host localhost --port 27017 \
  --db mydb --collection users \
  --out /backup/users.json

# 导出为CSV格式
mongoexport --host localhost --port 27017 \
  --db mydb --collection users \
  --type=csv \
  --fields name,email,age \
  --out /backup/users.csv

# 导出查询结果
mongoexport --host localhost --port 27017 \
  --db mydb --collection orders \
  --query '{"status": "completed"}' \
  --out /backup/completed_orders.json

# 导出排序后的数据
mongoexport --host localhost --port 27017 \
  --db mydb --collection users \
  --sort='{ "createdAt": -1 }' \
  --limit 1000 \
  --out /backup/recent_users.json

# 使用URI连接
mongoexport --uri="mongodb://localhost:27017/mydb" \
  --collection users \
  --out /backup/users.json

# 导出为JSON数组格式
mongoexport --host localhost --port 27017 \
  --db mydb --collection users \
  --jsonArray \
  --out /backup/users_array.json

# 格式化输出(pretty print)
mongoexport --host localhost --port 27017 \
  --db mydb --collection users \
  --pretty \
  --out /backup/users_pretty.json

mongoimport导入

bash
# mongoimport:从JSON或CSV文件导入数据

# 导入JSON文件
mongoimport --host localhost --port 27017 \
  --db mydb --collection users \
  --file /backup/users.json

# 导入JSON数组文件
mongoimport --host localhost --port 27017 \
  --db mydb --collection users \
  --jsonArray \
  --file /backup/users_array.json

# 导入CSV文件
mongoimport --host localhost --port 27017 \
  --db mydb --collection users \
  --type=csv \
  --headerline \
  --file /backup/users.csv

# 导入CSV并指定字段
mongoimport --host localhost --port 27017 \
  --db mydb --collection users \
  --type=csv \
  --fields name,email,age \
  --file /backup/users.csv

# 导入时忽略空字段
mongoimport --host localhost --port 27017 \
  --db mydb --collection users \
  --ignoreBlanks \
  --file /backup/users.json

# 导入时删除现有数据
mongoimport --host localhost --port 27017 \
  --db mydb --collection users \
  --drop \
  --file /backup/users.json

# 导入时更新现有数据(upsert)
mongoimport --host localhost --port 27017 \
  --db mydb --collection users \
  --upsertFields email \
  --file /backup/users.json

# 批量导入(指定批次大小)
mongoimport --host localhost --port 27017 \
  --db mydb --collection users \
  --batchSize 1000 \
  --file /backup/users.json

物理备份

复制数据文件

bash
# 物理备份:直接复制数据文件

# 方法一:停止MongoDB后复制(冷备份)

# 1. 停止MongoDB服务
sudo systemctl stop mongod

# 2. 复制数据目录
sudo cp -r /var/lib/mongodb /backup/mongodb_$(date +%Y%m%d)

# 3. 启动MongoDB服务
sudo systemctl start mongod

# 方法二:使用文件系统快照(热备份)

# 使用LVM快照
sudo lvcreate -L 10G -s -n mongodb_snapshot /dev/vg0/mongodb_lv

# 挂载快照
sudo mkdir /mnt/mongodb_snapshot
sudo mount /dev/vg0/mongodb_snapshot /mnt/mongodb_snapshot

# 复制快照数据
sudo cp -r /mnt/mongodb_snapshot /backup/mongodb_$(date +%Y%m%d)

# 卸载并删除快照
sudo umount /mnt/mongodb_snapshot
sudo lvremove /dev/vg0/mongodb_snapshot

使用WiredTiger检查点

bash
# 使用WiredTiger检查点进行一致性备份

# 1. 锁定数据库(阻止写入)
db.fsyncLock()

# 2. 复制数据文件
cp -r /var/lib/mongodb /backup/mongodb_$(date +%Y%m%d)

# 3. 解锁数据库
db.fsyncUnlock()

# 注意:锁定期间数据库只能读取不能写入

备份脚本

自动备份脚本

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

# 配置变量
MONGO_HOST="localhost"
MONGO_PORT="27017"
MONGO_USER="admin"
MONGO_PASS="password"
AUTH_DB="admin"
BACKUP_DIR="/backup/mongodb"
DATE=$(date +%Y%m%d_%H%M%S)
BACKUP_PATH="${BACKUP_DIR}/${DATE}"
RETENTION_DAYS=7

# 创建备份目录
mkdir -p ${BACKUP_PATH}

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

# 检查备份是否成功
if [ $? -eq 0 ]; then
    echo "备份成功: ${BACKUP_PATH}"
    
    # 压缩备份目录
    tar -czf ${BACKUP_PATH}.tar.gz -C ${BACKUP_DIR} ${DATE}
    rm -rf ${BACKUP_PATH}
    
    # 删除旧备份
    find ${BACKUP_DIR} -name "*.tar.gz" -mtime +${RETENTION_DAYS} -delete
    echo "已清理 ${RETENTION_DAYS} 天前的备份"
else
    echo "备份失败"
    exit 1
fi

echo "备份完成: $(date)"

定时备份

bash
# 使用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/full_backup_script.sh >> /var/log/mongodb_backup.log 2>&1

# 每小时备份oplog
0 * * * * /path/to/oplog_backup_script.sh >> /var/log/mongodb_backup.log 2>&1

备份验证

bash
#!/bin/bash
# 备份验证脚本

BACKUP_FILE=$1

# 检查文件是否存在
if [ ! -f "$BACKUP_FILE" ]; then
    echo "备份文件不存在: $BACKUP_FILE"
    exit 1
fi

# 检查压缩文件完整性
if [[ $BACKUP_FILE == *.gz ]]; then
    gzip -t $BACKUP_FILE
    if [ $? -ne 0 ]; then
        echo "压缩文件损坏: $BACKUP_FILE"
        exit 1
    fi
fi

# 测试恢复到临时数据库
TEMP_DB="test_restore_$(date +%Y%m%d_%H%M%S)"

mongorestore --host localhost --port 27017 \
    --db ${TEMP_DB} \
    --drop \
    --gzip \
    --archive=${BACKUP_FILE}

# 检查恢复的数据
DOCUMENT_COUNT=$(mongosh --quiet --eval "
    db.getSiblingDB('${TEMP_DB}').getCollectionNames().forEach(function(c) {
        print(db.getSiblingDB('${TEMP_DB}').getCollection(c).count());
    })
")

echo "恢复的文档数: ${DOCUMENT_COUNT}"

# 清理临时数据库
mongosh --quiet --eval "db.getSiblingDB('${TEMP_DB}').dropDatabase()"

echo "备份验证完成: $BACKUP_FILE"

本章小结

本章介绍了MongoDB备份与恢复的相关知识:

  1. 备份概述:了解不同备份类型的特点和适用场景
  2. mongodump备份:掌握逻辑备份工具的使用方法
  3. mongorestore恢复:学会使用恢复工具还原数据
  4. 数据导入导出:掌握mongoexport和mongoimport的使用
  5. 物理备份:了解直接复制数据文件的方法
  6. 备份脚本:学会编写自动备份和验证脚本

下一章,我们将学习性能优化,了解如何优化MongoDB性能。