默认情况下,mongorestore 既不会删除数据库,也不会覆盖已有的记录,而是尝试“附加(Append)”数据。
这就带来了一个巨大的风险:数据混合。
下面详细解释它的默认行为以及你应该怎么做。
1. 默认行为(不加 --drop 参数)
如果你直接运行你贴出的命令:
mongorestore --gzip --archive=... --nsInclude="testdata.*"
MongoDB 会按以下逻辑处理:
- 对于不存在的表(Collection):直接创建并导入数据。
- 对于已存在的表:它会尝试把备份里的数据插入进去。
- 遇到冲突(重点):
- MongoDB 的每条数据都有唯一的
_id。 - 如果备份里的某条数据
_id= 100,而数据库里已经有一条_id= 100 的数据(哪怕内容不一样)。 - 结果:报错
E11000 duplicate key error(重复键错误),跳过这条备份数据的恢复,保留数据库里原来的那条旧数据。 - 后果:你恢复完之后,数据库里是“原来没删掉的脏数据” + “原来没有但备份里有的新数据”的混合体。这通常不是你想要的恢复结果。
- MongoDB 的每条数据都有唯一的
2. 推荐做法:彻底覆盖(加上 --drop 参数)
通常我们恢复备份是因为数据乱了或者误删了,我们希望把数据库重置到备份时的那个状态。
你需要加上 --drop 参数。
它的作用是:在恢复某个集合(Collection)之前,先删除目标数据库里已存在的同名集合,然后再写入备份数据。
修改后的命令(推荐):
mongorestore \
--host 127.0.0.1 \
--port 27017 \
--drop \
--gzip \
--archive=/data/backup/testdata_20250101_020000.gzip \
--nsInclude="testdata.*"
3. 行为对比总结
| 场景 | 命令参数 | 已有数据库的处理 | 遇到相同_id 的数据 |
最终结果 | 适用场景 |
|---|---|---|---|---|---|
| 默认 | 无--drop |
保留,不删除 | 报错并跳过,保留现有的 | 新老数据混合 | 合并数据,或者往空库里恢复 |
| 覆盖 | 带 --drop |
先删除对应的表 | 不会遇到,因为表是新的 | 完全等同于备份时的状态 | 灾难恢复(最常用) |
4. 特别提醒
--drop是针对集合(表)级别的:它不会把整个testdata库删掉重建,而是如果你备份里有users表,它就删掉现有的users表重写;如果你库里还有个temp_log表,但备份里没有,temp_log表会原样保留,不会被删除。- 生产环境恢复建议:
在执行恢复命令之前,为了保险起见,建议先把当前的那个“有问题”的数据库再做一次备份(重命名一下,比如testdata_broken_backup)。万一备份文件有问题,你至少还能退回到刚才“坏掉”的状态,而不是两头空。