MongoDB 日志爆满 DiskQuotaExceeded 无法写入数据怎么办

文章导读
遇到 MongoDB 报 DiskQuotaExceeded 错误且无法写入数据,通常是因为 MongoDB Atlas 集群存储配额已满或自建实例磁盘空间耗尽。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

遇到 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 剩余,也可能无法完成事务提交。

MongoDB 日志爆满 DiskQuotaExceeded 无法写入数据怎么办

分步处理

按以下顺序操作,确保在释放空间的同时不损坏数据库文件。

步骤 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 工具管理。

MongoDB 日志爆满 DiskQuotaExceeded 无法写入数据怎么办

步骤 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()})

MongoDB 日志爆满 DiskQuotaExceeded 无法写入数据怎么办

检查点:

  • 命令返回 acknowledged: true 且无报错。
  • 服务器 df -h 显示可用空间(Available)大于 0。
  • MongoDB 日志中不再出现 DiskQuotaExceededENOSPC 相关错误。

常见坑

直接删除 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/