mongodump和mongorestore是mongodb官方推荐的备份恢复方案,通过spawn调用、--archive/--gzip单文件输出、--drop与--nsinclude精准控制、node-cron防重叠及时间戳命名+文件校验,可构建高可靠自动备份体系。

用 mongodump 和 mongorestore 做自动备份,别自己拼BSON流
Node.js 本身不内置 MongoDB 备份能力,硬写驱动层导出是自找麻烦。直接调用官方工具最稳——mongodump 生成 BSON + metadata JSON,mongorestore 能精确还原索引、权限和时序数据。前提是系统 PATH 里有这两个二进制,且 MongoDB 实例允许远程连接(或走本地 socket)。
常见错误:用 child_process.exec 跑 mongodump 却没设 timeout,遇到大库卡死进程;或忽略 --uri 中特殊字符(如密码含 @ 或 /),导致解析失败。
- 必须用
child_process.spawn,不是exec:避免 stdout 缓存爆炸(尤其 dump 出几百 MB BSON 时) -
--uri值务必用encodeURIComponent处理密码段,但不要全量 encode——只 enc 用户名/密码部分,host 和 db 名保持原样 - 加
--gzip和--archive参数,输出单文件,省去目录管理;恢复时对应加--gzip --archive
用 spawn 捕获实时进度与错误,别等 close 才处理
mongodump 运行中会持续往 stderr 打印进度(如 “12345 documents dumped”),而 close 事件只在结束时触发。如果备份中途因权限/网络失败,你得立刻知道,不能等到超时。
实操要点:
- 监听
stderr.on('data', chunk => {...}),用正则匹配/dumped (\d+) documents/或/Failed:/提前预警 - 设置
timeout: 30 * 60 * 1000(30 分钟),超时后调用child.kill('SIGTERM'),再等 5 秒未退出则SIGKILL - 检查
exitCode:0 是成功;非 0 时,signal为null表示程序报错(如认证失败),否则是被信号终止
示例片段:
const child = spawn('mongodump', [
'--uri', 'mongodb://user:pass@localhost:27017/mydb',
'--gzip',
'--archive=/backups/mydb-20241001.archive'
], { timeout: 1800000 });
恢复时指定 --drop 和 --nsInclude 防误删或漏表
直接跑 mongorestore 默认是“追加”,旧数据还在,容易引发重复 ID 或状态错乱。生产环境必须加 --drop 清空目标库再写入。
但全库恢复风险大——比如你只想回滚 orders 集合,结果 users 表也被覆盖了。这时用 --nsInclude 精确控制:
-
--nsInclude='mydb.orders':只恢复该集合 -
--nsInclude='mydb.*':只恢复 mydb 库下所有集合(排除其他库) - 搭配
--archive和--gzip,参数顺序无关,但必须和 dump 时一致
注意:--drop 不影响用户、角色等 admin 数据,只清 collection 和 index。
定时任务别只靠 setInterval,用 node-cron 或系统 crond
在 Node 进程里用 setInterval(() => backup(), 24 * 60 * 60 * 1000) 看似简单,但进程崩溃、部署重启后定时就丢了。更糟的是,两次备份并行启动可能压垮 MongoDB。
可靠做法:
- 用
node-cron库,支持表达式(如'0 2 * * *'每天 2 点),且自带互斥锁选项{ preventOverrun: true } - 或者干脆交给系统 crond:写个
backup.sh调用node backup.js,crond 天然防重叠、开机自启、日志分离 - 无论哪种,备份文件名必须含时间戳(
new Date().toISOString().slice(0,19).replace(/[:.]/g,'-')),否则覆盖风险极高
真正难的不是调用命令,而是判断“这次备份到底算不算成功”——得校验 archive 文件大小是否 > 1KB,再用 mongorestore --dryRun 快速试解析(v6.0+ 支持),否则备份文件损坏了你也发现不了。










