定义
GridFS 是一套用于存储和检索超出 BSON 文档大小上限的文件的规范,这个上限为 16 MiB。[1] 规范规定文件不再放入单个文档,而是被切分成若干数据块,每一块作为独立文档保存,因此单个文件的体积不再受单文档上限的约束。[3]
按照驱动侧规范的定义,GridFS 是驱动用来存取超出 16 MiB 的 BSON 二进制数据(类型 x05)的一套约定;写入时文件被拆成数据块,读取时再按记录重新拼合。[2] 它保存的对象既可以是磁盘上的实际文件,也可以是一段连续的大数据或输入流。[2]
原理
GridFS 在一个数据库中以“存储桶”为单位组织文件,桶由成组的集合构成,集合名以桶名为前缀,默认桶名是 fs,对应的两个集合是 fs.files 与 fs.chunks。[1] 存放文件内容的 chunks 集合里,每个文档记录一个数据块,字段包括数据块自身的 _id、指向父文件的 files_id、从 0 开始的分块序号 n,以及载荷 data。[2]
存放元数据的 files 集合中,每个文档对应一个已存文件,主要字段有 _id、以字节计的文件长度 length、每个数据块的大小 chunkSize、上传完成时间 uploadDate,以及可选的 filename、md5 和供应用自用的 metadata。[2] 一个文件应有多少个数据块,可以由 length 与 chunkSize 推算出来。[2]
数据块的默认大小为 255 KiB,文件按此大小切分,仅最后一块的实际大小以需要为准;不超过一个块大小的文件只会产生唯一的末块。[1] 关于 255 KiB 这一取值的由来,规范给出的解释是在 MMAPv1 存储引擎下,这样的块文档正好能够放进服务端预留的 256 KiB 内存区段,从而充分利用填充空间。
为支持高效读取,规范要求 chunks 集合上存在 files_id 与 n 的组合唯一索引,files 集合上存在 filename 与 uploadDate 的组合索引;驱动在首次写入前会检查 files 集合是否为空,若为空且索引不存在则创建索引。[2] 读取时,驱动先从 files 集合取出元数据,再依据其中的信息到 chunks 集合重新拼装出完整文件。[4]
发展历程
GridFS 被设计为一种规范而非服务端功能,MongoDB 服务端没有专门处理 GridFS 的代码,全部工作由客户端驱动完成。[5] 这样安排的好处是,任何遵循同一约定的驱动都能读取其他驱动写入的文件。[5]
在 MongoDB 手册的早期版本中,files 集合里的 chunkSize 默认值曾为 256 KB,自 2.4.10 版本起改为 255 KB。[6] 驱动侧规范随后对这一数据模型做了澄清与整理,并把一部分字段列为废弃。[2]
规范还记录了若干后续调整:2016 年 5 月允许应用自定义文件 id,2016 年 10 月要求驱动能够处理不同的 length 与 chunkSize 数值类型并加入读关注(ReadConcern)配置,2018 年 1 月将 MD5 标记为废弃并提供关闭 MD5 计算的选项,2022 年 1 月要求按客户端操作超时规范施加超时。 MD5 被废弃的原因是该算法为 FIPS 140-2 所禁止,在处于 FIPS 模式的系统上可能无法提供。
应用
使用 GridFS 存取文件有两条途径:一是通过 MongoDB 驱动,二是使用 mongofiles 命令行工具。[1] 驱动侧提供存储桶对象及其上传、下载、重命名等方法,上传既可以从内存数据发起,也可以从输入流发起。[4]
GridFS 适用的场合包括:文件大于 16 MiB;需要在系统中保存数量不受目录条数限制的文件;需要读取大文件的局部而不把整个文件读入内存,例如直接跳到音视频的中段。[1] 借助地理分布的副本集,文件及其元数据还可以随数据库复制自动分散到多个 mongod 实例和设施中。[1]
当所有文件都小于 16 MiB 时,规范建议改用 BinData 数据类型把每个文件存入单个文档,而不必引入 GridFS。[1] 若必须对 chunks 集合分片,应选择能够把同一文件的所有数据块路由到同一分片的片键;files 集合通常较小,一般无需分片。
局限
GridFS 不支持多文档事务。[1] 由于存取过程涉及跨集合的多个文档操作,而 MongoDB 目前无法跨集合原子地完成这些操作,因此无法在避免 GridFS 客户端之间竞态的前提下改动已存储的文件。
如果需要原子地更新整个文件的内容,就不应使用 GridFS;可行的替代做法是为每个文件保留多个版本,在元数据中标记当前版本,上传新版本后以原子操作用来更新表示“最新”状态的字段,再按需删除旧版本。[1]
写操作或删除操作中途失败时,chunks 集合中可能留下 files_id 不再对应任何 files 文档的数据块,这类数据块被称为孤儿块。[2] 此外,规范并不规定驱动在发现文件带有多余数据块时报告错误,驱动可以选择忽略这些多余块。
参见
参考资料
- GridFS - Database Manual v8.0 [引用日期2026-10-14]
- gridfs-spec [引用日期2026-10-14]
- 自管理部署的 GridFS [引用日期2026-10-14]
- mongodb.ac.cn 上的网页 [引用日期2026-10-14]
- github.com 上的网页 [引用日期2026-10-14]
- GridFS Reference¶ [引用日期2026-10-14]