重分片失败报 NotEnoughDiskSpace 时,需先检查真实磁盘与内存压力,清理旧 oplog,配置 WiredTiger 的 eviction_target=80 和 eviction_trigger=90,并扩大 oplog 容量,监控数据量、chunk 分布及 inodes 使用率。

重分片失败报 NotEnoughDiskSpace 怎么办
直接原因是 MongoDB 在迁移 chunk 时,目标分片需要额外空间存放副本数据(包括临时的迁移中 chunk、oplog 缓冲、WiredTiger cache 副作用),而磁盘已接近 90% 使用率。MongoDB 5.0 默认拒绝在剩余空间 10GB 或 5% 的分片上启动迁移——这不是配置项,是硬限制。
- 检查真实可用空间别只看
df -h:WiredTiger 日志和缓存可能占大量未释放空间,用db.serverStatus().metrics.repl.buffer和db.runCommand({ "serverStatus": 1 }).wiredTiger.cache看实际内存/磁盘压力 - 临时腾空间最有效的是清理旧 oplog:执行
db.runCommand({ "logRotate": 1 })(需开启日志轮转),再删掉/var/log/mongodb/mongod.log.*归档文件 - 禁止用
rm -rf直接删data/db/下的*journal或*wt文件——这会破坏 WiredTiger 元数据,导致分片无法启动
如何安全预留 20% 磁盘空间给重分片
不是靠“多买磁盘”,而是让 MongoDB 主动感知并尊重这个水位。关键在 wiredTiger.engineConfig.configString 和 storage.wiredTiger.engineConfig.cacheSizeGB 的协同控制:
- 在每个分片的
mongod.conf中显式设置:storage:<br> wiredTiger:<br> engineConfig:<br> configString: "cache_size=8G,eviction_target=80,eviction_trigger=90"
其中eviction_target=80表示当 cache 占用达 80%,WiredTiger 开始主动驱逐页;eviction_trigger=90是硬上限,超了就阻塞写入——这间接保护了磁盘不被填满 -
cacheSizeGB必须小于物理内存的 60%,否则 OS OOM Killer 可能干掉mongod进程;设为8时,对应磁盘预留至少20GB(按 chunk 平均大小估算) - 重启分片前,先运行
db.adminCommand({ "setParameter": 1, "wiredTigerEngineConfigString": "eviction_target=80" })热生效部分参数(仅限 5.0+)
重分片期间监控哪些指标才不会漏掉空间告警
依赖 db.printShardingStatus() 或 Atlas UI 的“分片容量”视图远远不够。必须盯住三个实时指标:
-
db.runCommand({ "top": 1 }).totals["dataSize"].totalSize:当前分片总数据量,每 5 分钟查一次,确认增长是否异常(比如某集合突然暴涨) -
db.getSiblingDB("config").chunks.countDocuments({ "shard": "shard01" }):对比各分片 chunk 数量,若某分片 chunk 数突增 30% 以上,说明迁移正密集写入,立刻检查其磁盘 I/O wait(iostat -x 1) - 系统级:监控
/proc/mounts对应挂载点的inodes使用率——df -i显示 95%+ 时,即使磁盘有空余,WiredTiger 也会因无法创建新文件而卡住迁移
紧急情况下跳过空间检查的风险与操作
MongoDB 5.0 不提供关闭 NotEnoughDiskSpace 检查的开关。所谓“跳过”只有两种真实路径,且都有明确副作用:
- 手动修改 config server 的
shards集合中对应分片的host字段,把端口改成一个临时未使用的(如shard01/localhost:27018),等重分片完成后再改回——这会让 balancer 认为该分片“暂时离线”,从而暂停往它迁移,但会导致部分 chunk 长期失衡 - 用
mongodump+mongorestore --drop清空低优先级数据库,腾出空间后再重试重分片——注意mongorestore默认不保留分片键,必须加--shardedCollection参数指定分片集合名,否则恢复后数据无法路由
真正容易被忽略的是:重分片过程中,secondary 节点的 local.oplog.rs 大小会随迁移节奏剧烈波动,如果使用默认的 5% 磁盘配额,它可能吃掉本该留给 chunk 迁移的空间。务必在所有分片节点上运行 db.getSiblingDB("local").runCommand({ "collMod": "oplog.rs", "oplogSizeMB": 10240 }) 手动扩大 oplog(需重启 mongod 生效)。


















