MongoDB 3.6 的 mongodump 默认不备份 GridFS 的 fs.files 和 fs.chunks 集合,因其被视为内部命名空间;必须显式指定集合导出,并用 --drop 配合 mongorestore 全库还原以确保关联完整性。

MongoDB 3.6 的 mongodump 和 mongorestore 无法直接迁移 GridFS 数据——它们默认忽略 fs.files 和 fs.chunks 集合,除非显式指定。
为什么 mongodump 不备份 GridFS 默认失效
GridFS 实际是两个集合:fs.files(元数据)和 fs.chunks(二进制分块)。mongodump 默认只 dump 用户创建的「顶层集合」,而 fs.* 被视为内部命名空间,不自动包含。
- 执行
mongodump --db myapp后检查 dump 目录,会发现没有fs.files.bson或fs.chunks.bson - 即使加
--collections也不行:它只接受集合名列表,不支持通配符或前缀匹配 - 错误现象:restore 后应用调用
GridFSBucket.find()返回空,或抛FileNotFound
必须显式导出 fs.files 和 fs.chunks 两个集合
不能依赖数据库级 dump,得按集合粒度分别导出,并确保顺序和一致性。
- 先锁库或停写(若业务允许),否则可能因 chunks 写入未完成导致文件损坏
- 导出命令需成对执行,且使用相同
--host、--port、--username等连接参数 - 示例(假设数据库叫
myapp,GridFS 前缀为默认fs):
mongodump --db myapp --collection fs.files --out /backup/gridfs/ mongodump --db myapp --collection fs.chunks --out /backup/gridfs/
注意:--out 路径必须相同,否则 mongorestore 无法自动识别关联关系。
mongorestore 时要避免集合名冲突与重复插入
mongorestore 不会自动跳过已存在文档,且 GridFS 的 _id 是唯一索引,重复导入会报 E11000 duplicate key 错误。
- 若目标库已有同名
fs.files或fs.chunks,先清空(慎用!):mongo myapp --eval "db.fs.files.deleteMany({})"mongo myapp --eval "db.fs.chunks.deleteMany({})" - 或者用
--drop参数(推荐):mongorestore --drop --db myapp /backup/gridfs/myapp/ - 务必确认路径指向的是
/backup/gridfs/myapp/(即 dump 生成的子目录),不是上层/backup/gridfs/ - 不要用
--collection单独 restore,会丢失 GridFS 关联逻辑;必须 restore 整个 db 子目录
验证迁移是否完整的关键检查点
迁移后不能只看集合是否存在,得验证文件逻辑完整性。
- 查文件数是否一致:
mongo myapp --eval "db.fs.files.countDocuments({})"对比源库 - 查最大
chunkSize是否统一(常见为 255KB):mongo myapp --eval "db.fs.files.findOne({}, {chunkSize: 1})" - 随机 pick 一个
_id,用驱动代码或 shell 手动读取:db.fs.files.findOne({_id: ObjectId("...")})→ 检查length和filenamedb.fs.chunks.find({files_id: ObjectId("...")}).count()→ 应等于Math.ceil(length / chunkSize) - 特别注意:MongoDB 3.6 的
mongorestore不校验 chunk 数据 CRC,损坏 chunk 只能在应用读取时报错
真正麻烦的不是导出还原,而是迁移过程中应用仍在写 GridFS —— 这需要协调停机窗口,或改用 mongosync(3.6 不支持)或自研双写兜底。旧版本没热迁移方案,这点容易被低估。


















