默认情况下,mongorestore 既不会删除数据库,也不会覆盖已有的记录,而是尝试“附加(Append)”数据。

这就带来了一个巨大的风险:数据混合

下面详细解释它的默认行为以及你应该怎么做。

1. 默认行为(不加 --drop 参数)

如果你直接运行你贴出的命令:

mongorestore --gzip --archive=... --nsInclude="testdata.*"

MongoDB 会按以下逻辑处理:

  1. 对于不存在的表(Collection):直接创建并导入数据。
  2. 对于已存在的表:它会尝试把备份里的数据插入进去。
  3. 遇到冲突(重点)
    • MongoDB 的每条数据都有唯一的 _id
    • 如果备份里的某条数据 _id = 100,而数据库里已经有一条 _id = 100 的数据(哪怕内容不一样)。
    • 结果:报错 E11000 duplicate key error(重复键错误),跳过这条备份数据的恢复,保留数据库里原来的那条旧数据。
    • 后果:你恢复完之后,数据库里是“原来没删掉的脏数据” + “原来没有但备份里有的新数据”的混合体。这通常不是你想要的恢复结果。

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)。万一备份文件有问题,你至少还能退回到刚才“坏掉”的状态,而不是两头空。