必须先清理孤儿chunk再按顺序compact:先db.runcommand({compact: "fs.chunks"}),再db.runcommand({compact: "fs.files"}),且仅在primary节点执行;否则空间不释放。

为什么 db.runCommand({compact: "fs.chunks"}) 在 MongoDB 7.0 里没效果
不是命令写错了,是执行环境或顺序不对。MongoDB 7.0 的 WiredTiger 引擎仍沿用“标记可复用、不还给 OS”的策略,compact 仅重写 .wt 文件并整理内部块,但必须满足三个硬性前提:连的是 primary 节点、先 compact fs.chunks、再 compact fs.files。在 secondary 上执行、或只 compact 其中一个集合,都会导致空间无变化。
执行 compact 前必须清理孤儿 chunk
很多人删了 fs.files 文档就以为完事了,结果 fs.chunks 里还堆着大量 files_id 不在 fs.files 中的“幽灵分片”。这些孤儿 chunk 不会被 compact 扫描到,永远占着磁盘。
- 先运行
db.fs.chunks.deleteMany({"files_id": {$nin: db.fs.files.distinct("_id")}})清理孤儿 - 确认无并发写入(否则可能误删正在上传的 chunk)
- 再查一遍:
db.fs.chunks.countDocuments({"files_id": {$nin: db.fs.files.distinct("_id")}})应返回 0
compact 过程中磁盘临时爆满怎么办
compact 会重写整个 .wt 文件,期间需额外空间 ≈ 当前 fs.chunks 数据文件大小 × 1.2。如果 df -h 显示剩余空间不足,命令会卡住甚至失败。
- 执行前务必检查:
db.fs.chunks.stats().size和磁盘可用空间 - 避免在
/var/lib/mongodb所在分区只剩 - 若空间吃紧,直接跳过 compact,改用
mongodump+drop+mongorestore
Atlas 或托管服务上 compact 失效的常见原因
云环境(如 MongoDB Atlas)默认禁用或限制 compact,部分平台会将其转为后台异步任务,甚至被快照机制延迟生效。
- 先查文档确认是否允许:
db.runCommand({getCmdLineOpts: 1})看disableCompact是否为 true - Atlas 用户应优先走「Cluster Resync」或「Storage Optimization」后台功能
- 若报错
"command compact not allowed",说明平台已屏蔽,别硬试











