遇到 MongoDB 报 DiskQuotaExceeded 错误且无法写入数据,通常是因为 MongoDB Atlas 集群存储配额已满或自建实例磁盘空间耗尽。
最推荐的处理方向是先确认存储使用率,再清理非必要日志或归档旧数据,若使用托管服务则需升级存储配额。
最重要的风险边界是不要直接删除 data 目录下的数据文件,否则会导致数据库无法启动。
先说结论:DiskQuotaExceeded 代表存储资源已达上限,必须释放空间或扩容才能恢复写入。
- 先确认:区分是 MongoDB Atlas 配额限制还是自建服务器磁盘物理空间不足。
- 先处理:优先清理 MongoDB 日志文件或归档冷数据,避免直接操作数据文件。
- 再验证:通过写入测试命令和磁盘使用率检查确认空间已释放。
命令速用版
以下命令用于快速检查磁盘空间和 MongoDB 内部存储状态,适用于 Linux 自建环境。
# 检查磁盘整体使用率
df -h
# 检查 MongoDB 数据目录大小
du -sh /var/lib/mongodb
# 进入 Mongo Shell 查看数据库大小
mongosh `--eval` "db.stats()"
# 查看当前慢查询或锁情况,确认是否有阻塞
db.currentOp({"secs_running": {"$gt": 10}})若使用 MongoDB Atlas,需在控制台查看 Storage 指标,无法通过命令行直接扩容。
为什么会这样
DiskQuotaExceeded 错误通常由存储配额限制触发,而非单纯的文件系统权限问题。
在 MongoDB Atlas 等托管服务中,该错误对应 Error Code 125,表示集群分配的存储空间已用完,写入操作会被拒绝以保护数据完整性。
在自建环境中,虽然操作系统通常返回 No space left on device,但部分容器化部署或云盘挂载场景下也会映射为配额超限。
WiredTiger 存储引擎需要预留少量磁盘空间用于元数据操作,当磁盘完全写满时,即使只有几 MB 剩余,也可能无法完成事务提交。
分步处理
按以下顺序操作,确保在释放空间的同时不损坏数据库文件。
步骤 1:确认存储类型和剩余空间
登录服务器执行 df -h,若使用率接近 100%,则需清理空间。若使用 Atlas,登录控制台查看 Storage 使用率图表。
步骤 2:安全清理日志文件
MongoDB 日志文件通常位于 /var/log/mongodb/ 或配置文件中指定的 systemLog.path。
不要直接使用 rm 删除正在写入的日志文件,否则文件句柄未释放,空间不会回收。
正确做法是清空文件内容:
sudo truncate -s 0 /var/log/mongodb/mongod.log或者配置日志轮转(log rotation),使用
logrotate工具管理。步骤 3:归档或删除冷数据
若日志清理后空间仍不足,需处理业务数据。使用
mongodump备份旧数据到外部存储,然后使用db.collection.deleteMany()删除过期文档。删除数据后,WiredTiger 不会立即归还空间给操作系统,需执行
compact命令或重建索引来整理碎片,但此操作消耗资源,建议在低峰期进行。步骤 4:扩容存储(针对 Atlas 或云盘)
若数据均不可删除,必须升级存储规格。Atlas 用户需在 Cluster 设置中增加 Storage Size。自建用户需扩容云盘并调整文件系统大小。
怎么验证是否生效
执行写入操作并观察日志,确认错误不再出现。
验证命令:
# 在 mongosh 中尝试插入一条测试数据 db.test_collection.insertOne({"check": "disk_space_fixed", "timestamp": new Date()})检查点:
- 命令返回
acknowledged: true且无报错。 - 服务器
df -h显示可用空间(Available)大于 0。 - MongoDB 日志中不再出现
DiskQuotaExceeded或ENOSPC相关错误。
常见坑
直接删除 data 目录文件:严禁直接 rm /var/lib/mongodb/*.wt 等数据文件,这将导致数据库无法启动且数据永久丢失。
忽略 Oplog 大小:在副本集架构中,Oplog 可能占用大量空间。若不需要太长的回滚窗口,可适当调整 oplogSizeMB 配置。
清理日志后未重启服务:某些旧版本或特定配置下,清空日志文件后可能需要重启 MongoDB 服务才能重新正确句柄,但通常 truncate 操作即时生效。
容器磁盘配额:若运行在 Docker 或 Kubernetes 中,需检查 Container 层面的 storage limit,而非仅看节点磁盘。
常见问题
重启 MongoDB 能解决 DiskQuotaExceeded 吗?
不能,重启无法释放磁盘空间,除非重启过程中触发了日志轮转或临时文件清理。
清理日志后为什么磁盘空间没变化?
可能是因为使用了 rm 命令而非 truncate,文件句柄仍被进程占用,空间未归还操作系统。
Atlas 集群爆满后数据会丢失吗?
不会立即丢失,但写入会被拒绝,导致业务不可用,需尽快扩容或清理数据。
如何预防日志再次爆满?
配置 logrotate 自动轮转日志,并设置 MongoDB 的 maxFileSize 参数限制单个日志文件大小。
参考来源
- MongoDB 官方文档 - Manual: https://www.mongodb.com/docs/manual/
- MongoDB 官方文档 - Atlas Storage Troubleshooting: https://www.mongodb.com/docs/atlas/