☰
Linux下MongoDB定时备份方案:mongodump与crontab实战
2026/10/27 14:40:50 网站建设 项目流程

数据这玩意儿,平时躺在库里岁月静好,一旦出问题就是事故现场。我见过太多团队在业务跑得正欢的时候,压根没想过备份这回事,等到某天误删了一个集合、磁盘写满导致数据文件损坏,或者一次不小心的批量更新把关键字段全刷成了同一个值,才开始满世界找恢复手段。所以这篇内容我想聊的是:在Linux环境下,怎么给MongoDB搭一套靠谱的定时备份方案,做到数据自动落盘、按天归档、出问题能快速回滚。核心关键词就是MongoDB备份、mongodump、crontab定时任务、数据恢复,这几个东西串起来就是一套完整的兜底体系。不管你是刚接手一台跑着MongoDB的服务器的新手运维,还是自己写小项目需要给数据上保险的开发者,这套方案都能直接抄作业,配置量不大,但覆盖了从备份脚本编写、定时调度、日志记录到恢复验证的完整链路。

1. 方案整体设计与选型思路

1.1 为什么选mongodump而不是直接拷数据文件

给MongoDB做备份,摆在面前的路其实有好几条:直接停库拷贝数据目录、用文件系统快照、用mongodump逻辑导出、用mongorestore配合副本集做热备。我先把选型逻辑讲清楚,因为选错了后面全是坑。

直接拷贝数据目录(比如把 /var/lib/mongodb 整个打包)是最粗暴的方式,但它要求数据库处于停止状态或者至少是干净关闭状态,否则拷出来的文件可能处于不一致状态,恢复时直接报错。生产环境不可能为了备份停库,所以这条路基本排除。文件系统快照(LVM快照、云盘快照)速度快、对业务影响小,但它依赖底层存储支持,而且快照恢复是整盘级别的,粒度太粗,你想单独恢复某个集合就做不到。

mongodump 是MongoDB官方自带的逻辑备份工具,它把数据导出成BSON格式文件,配合mongorestore可以精确恢复到集合级别甚至文档级别。它的优势在于:不停库、粒度细、跨版本兼容性好、备份文件可读可迁移。缺点是数据量大时导出慢、对数据库有一定读压力。但对于绝大多数中小规模业务(数据量在几十GB以内),mongodump完全够用,而且它是官方工具,随MongoDB安装包一起提供,不需要额外装东西。

提示:如果你的单库数据量超过几百GB,mongodump的全量导出时间会很长,这时候要考虑增量备份方案或者副本集从节点备份,把读压力转移到从库上。本文方案针对的是常规规模场景。

所以整体设计思路就定了:用 mongodump 做逻辑备份,用 shell 脚本封装备份逻辑(包括目录创建、文件压缩、过期清理、日志记录),用 crontab 做定时调度。这套组合的特点是零外部依赖、纯系统自带能力、脚本可读可改,出问题容易排查。

1.2 备份策略的几个关键决策

方案里有两个绕不开的决策点,我逐个说。

第一个是全量还是增量。mongodump 本身只支持全量导出(它没有原生的增量备份能力),所以定时任务跑的都是全量。全量备份的好处是恢复简单——拿到最新一份备份直接还原就行,不依赖备份链。坏处是占空间、耗时间。我的处理办法是:每天全量备份一次,保留最近N天,超期自动删除。对于数据量不大的场景,每天全量完全可接受;数据量大的话,可以调整为每周全量+每天只备份关键集合,或者把备份频率降到每天一次但错开业务高峰。

第二个是备份文件存哪里。最省事的做法是存在本机另一个目录,但这有个致命问题:如果整台机器挂了或者磁盘坏了,备份和数据一起没。所以稳妥的做法是备份到独立挂载的磁盘或者远程存储(比如挂载的NFS、对象存储)。本文脚本会预留一个备份根目录变量,你可以指向本地独立分区,也可以指向挂载的远程路径,脚本本身不关心存储介质,只负责往指定目录写。

第三个是要不要压缩。mongodump 支持--gzip参数直接输出压缩文件,能显著减小体积(BSON文本压缩率通常不错)。我建议开启,代价是导出时多一点点CPU开销,但省下的磁盘空间和传输时间很值。脚本里我会用 gzip 压缩整个备份目录,这样一份备份就是一个 tar.gz 包,管理起来清爽。

2. 环境准备与核心工具确认

2.1 确认MongoDB工具链是否齐全

动手写脚本之前,先确认服务器上 mongodump 和 mongorestore 这两个命令能不能用。它们通常随MongoDB服务端一起安装,但有些精简安装或者容器环境里可能只有 mongod 没有工具集。

which mongodump which mongorestore mongodump --version

如果which找不到,说明工具没装。不同发行版的安装方式不一样,以常见的包管理为例,MongoDB官方源里的mongodb-org-tools包就包含这些工具。装好之后再验证一次版本,注意 mongodump 的版本最好和服务端版本接近,跨大版本导出可能有兼容性问题。

注意:mongodump 的版本不要低于服务端太多。比如服务端是6.x,工具是4.x,导出时可能遇到认证机制或BSON格式不兼容。版本对齐是最省心的做法。

2.2 准备备份目录与权限

备份要写文件,就得有目录和权限。我习惯把备份统一放在/data/backup/mongodb这种独立路径下,方便管理和挂载独立磁盘。创建目录并确认运行备份的用户有写权限:

mkdir -p /data/backup/mongodb chown -R $(whoami):$(whoami) /data/backup/mongodb

这里有个细节:crontab 执行任务时的环境和你在终端里手动执行不一样,PATH 可能不完整,用户身份也可能不同。所以脚本里所有命令尽量用绝对路径,或者在脚本开头显式设置 PATH。这一点后面写脚本时会重点处理,是新手最容易踩的坑之一。

2.3 数据库连接信息的准备

mongodump 连接数据库需要知道地址、端口、认证信息。如果数据库开了认证(生产环境基本都开),需要提供用户名密码和认证库。这里有个安全考量:密码不要明文写在脚本里,最好放在一个权限受限的配置文件里,脚本去读取。

我通常建一个/etc/mongodb-backup.cnf这样的配置文件,权限设成 600,内容大致是:

host=127.0.0.1 port=27017 username=backup_user password=你的密码 authenticationDatabase=admin

然后脚本里用--config参数引用它。这样脚本本身可以随便看,密码不会泄露。备份用的账号建议单独建一个只有backup和read角色的用户,最小权限原则,别拿管理员账号跑备份。

3. 备份脚本的完整实现与逐段解析

3.1 脚本骨架与变量定义

先看整体结构。脚本我命名为mongo_backup.sh,放在/usr/local/bin/下方便调用。开头定义一组变量,把路径、保留天数、日志位置都集中管理,改配置只改这一块。

#!/bin/bash # 基础配置 BACKUP_ROOT="/data/backup/mongodb" DATE=$(date +%Y%m%d_%H%M%S) BACKUP_DIR="${BACKUP_ROOT}/${DATE}" LOG_FILE="${BACKUP_ROOT}/backup.log" KEEP_DAYS=7 MONGO_CONFIG="/etc/mongodb-backup.cnf" # 确保PATH完整,crontab环境下很关键 export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

DATE用精确到秒的时间戳做目录名,好处是同一台机器上多次备份不会互相覆盖,也方便按时间排序找最新备份。KEEP_DAYS=7表示保留最近7天的备份,这个值按你的磁盘容量和恢复需求调整。export PATH那行是血泪教训——crontab 默认的 PATH 往往很短,不显式设置的话脚本里调用的命令可能找不到。

3.2 备份执行与错误处理

核心备份动作就一行 mongodump,但外面要包一层错误判断,备份失败得能感知到。

echo "[$(date '+%Y-%m-%d %H:%M:%S')] 开始备份" >> "${LOG_FILE}" mkdir -p "${BACKUP_DIR}" mongodump --config="${MONGO_CONFIG}" \ --out="${BACKUP_DIR}" \ --gzip \ --quiet >> "${LOG_FILE}" 2>&1 if [ $? -ne 0 ]; then echo "[$(date '+%Y-%m-%d %H:%M:%S')] 备份失败,请检查" >> "${LOG_FILE}" exit 1 fi echo "[$(date '+%Y-%m-%d %H:%M:%S')] 备份完成: ${BACKUP_DIR}" >> "${LOG_FILE}"

这里几个参数值得展开说。--out指定输出目录,mongodump 会在里面按数据库名建子目录,每个集合导出成.bson.gz文件。--gzip开启压缩,前面说过能省空间。--quiet减少冗余输出,日志干净些。$?判断上一条命令的退出码,非0说明备份出错,直接退出并记录,避免后续压缩一个残缺的备份。

提示:如果只想备份特定数据库,加--db=库名;只想备份特定集合,加--collection=集合名。全库备份不加这些参数即可。

3.3 打包压缩与过期清理

备份目录里是一堆散文件,打包成一个 tar.gz 更利于归档和传输。

cd "${BACKUP_ROOT}" tar -czf "${DATE}.tar.gz" "${DATE}" && rm -rf "${DATE}" # 清理过期备份 find "${BACKUP_ROOT}" -name "*.tar.gz" -type f -mtime +${KEEP_DAYS} -delete echo "[$(date '+%Y-%m-%d %H:%M:%S')] 已清理${KEEP_DAYS}天前的备份" >> "${LOG_FILE}"

打包成功后删掉原始目录,避免磁盘上同时存在散文件和压缩包占双份空间。find配合-mtime +7删除7天前的文件,-delete直接删。这里要注意-mtime的语义是“修改时间在N天以前”,+7表示超过7天,正好符合保留7天的需求。

3.4 脚本完整版与执行权限

把上面几段拼起来就是完整脚本。给执行权限:

chmod +x /usr/local/bin/mongo_backup.sh

先手动跑一次验证:

/usr/local/bin/mongo_backup.sh

跑完去/data/backup/mongodb下看有没有生成日期.tar.gz,日志里有没有“备份完成”。手动跑通是配置定时任务的前提,别跳过这步直接上 crontab,否则出了问题你分不清是脚本问题还是调度问题。

4. crontab定时调度配置与验证

4.1 编写定时任务

用crontab -e编辑当前用户的定时任务,加一行:

0 2 * * * /usr/local/bin/mongo_backup.sh

这行的意思是每天凌晨2点执行备份脚本。选凌晨2点是因为业务低峰,mongodump 的读压力对线上影响最小。如果你的业务是全天候高峰,可以选一个相对空闲的时段,比如凌晨4点。

注意:crontab 里的命令必须用绝对路径,因为 cron 环境的 PATH 和你登录 shell 的不一样。脚本内部虽然设置了 PATH,但调用脚本本身这个路径也得写全。

4.2 验证定时任务是否生效

配完别干等,用几种方式验证。先看 cron 服务在不在跑:

systemctl status cron

不同发行版服务名可能是cron或crond。再看当前用户的定时任务列表:

crontab -l

确认那行任务在。然后可以临时把时间改成几分钟后,观察是否自动执行、日志是否追加。验证完再改回凌晨2点。这一步很多人省了,结果任务根本没触发,等到真需要恢复时才发现备份是空的。

4.3 日志轮转的考虑

备份日志会一直追加,时间长了文件变大。简单处理是在脚本里加个判断,日志超过一定大小就清空或归档。更规范的做法是配 logrotate,但对备份日志来说,脚本里加几行就够:

if [ -f "${LOG_FILE}" ] && [ $(stat -c%s "${LOG_FILE}") -gt 10485760 ]; then mv "${LOG_FILE}" "${LOG_FILE}.old" fi

超过10MB就把旧日志改名,新日志重新写。这样日志不会无限膨胀,排查问题时也不会翻半天。

5. 恢复验证与常见问题排查

5.1 备份能不能恢复才是关键

备份做完不验证,等于没备份。定期挑一份备份做恢复演练,是这套方案里最容易被忽略但最重要的一环。恢复用 mongorestore:

# 先解压 tar -xzf 20240101_020000.tar.gz # 恢复到指定库(建议恢复到测试库,别直接覆盖生产) mongorestore --config=/etc/mongodb-backup.cnf \ --gzip \ --nsInclude="你的库名.*" \ --drop \ ./20240101_020000/你的库名

--gzip对应备份时的压缩,--nsInclude指定只恢复某个库,--drop表示恢复前先删掉目标库里的同名集合(谨慎使用,恢复演练时指向测试库就安全)。恢复完连上去查几条数据,确认集合数量和文档数量对得上,这才算验证通过。

5.2 常见问题速查表

实际操作中遇到的问题五花八门,我把高频的整理成表,方便对照排查。

现象可能原因处理办法
脚本手动能跑,crontab不执行cron环境PATH不全或脚本无执行权限脚本内设PATH,chmod +x,命令用绝对路径
备份文件为空或很小认证失败或连接不上数据库检查配置文件账号密码、认证库、host端口
mongodump报版本不兼容工具版本与服务端差距过大升级mongodb工具包到与服务端接近的版本
磁盘被备份占满保留天数过多或未清理调小KEEP_DAYS,确认find清理逻辑生效
恢复时报集合已存在未加--drop或目标库有数据恢复演练指向测试库,或按需加--drop
日志无输出日志路径无写权限检查目录权限,确保运行用户可写

5.3 几个实操心得

说几个文档里不常写但很实用的点。第一,备份账号一定要单独建,只给backup和read权限,别图省事用 root 账号,一旦配置文件泄露损失可控。第二,备份目录最好在独立磁盘上,用df -h定期看一眼剩余空间,磁盘满了备份会静默失败(脚本里虽然有错误判断,但磁盘满时连日志都可能写不进去)。第三,恢复演练至少每季度做一次,别等真出事才第一次用 mongorestore,那时候手忙脚乱容易出错。

还有个小技巧:可以在备份脚本最后加一行,把最新备份的文件名和大小写进一个latest.txt,监控系统读这个文件就能判断备份是否正常,比翻日志方便。这套方案不复杂,但把备份、压缩、清理、日志、验证串成了闭环,跑起来之后基本不用操心,数据安全这件事,靠的就是这种平时不起眼、关键时刻能救命的自动化兜底。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询