答案是副本集从节点默认禁止allowDiskUse,仅PRIMARY和mongos支持磁盘辅助聚合;必须强制readPreference=primary并验证ismaster为true。

从节点执行聚合时提示“Sort exceeded memory limit”或“allowDiskUse is not allowed”
副本集从节点默认禁止 allowDiskUse:true,即使你在客户端显式传入,mongod 也会直接拒绝。这不是权限配置遗漏,而是 MongoDB 的硬性限制:**从节点不支持磁盘辅助聚合(disk-based aggregation)**。该限制存在于 4.2–7.x 全系列,且与 readPreference 设置无关——哪怕你强制读取主节点,只要聚合命令实际路由到从节点(例如在 secondaryPreferred 下主节点高负载被跳过),就会失败。
真正能用 allowDiskUse:true 的节点类型只有主节点和 mongos
必须明确:MongoDB 只允许两类角色执行带磁盘落盘的聚合:
- 副本集中的
PRIMARY节点(需确保写关注和读偏好不绕过它) - 分片集群中的
mongos进程(它负责合并各分片结果,且自身可启用磁盘)
从节点(SECONDARY)的存储引擎(WiredTiger 或 In-Memory)均不开放临时磁盘目录写入通道。即使你手动修改 storage.directoryPerDB: true 或挂载可写 volume,mongod 进程启动时也不会初始化相关路径,运行时调用也会被内核级策略拦截。
绕过限制的实操方案:改读偏好 + 确保主节点承载聚合
如果你的应用必须在副本集环境下跑大聚合,唯一可靠路径是让聚合始终落在主节点上:
- 连接字符串中显式指定
readPreference=primary(驱动默认值,但务必确认未被代码覆盖) - 聚合前先执行
db.runCommand({isMaster: 1}),检查返回的ismaster字段是否为true,避免因选举刚结束导致连接残留到旧主 - 若使用
mongosh,不要依赖rs.secondaryOk()—— 它只影响读操作路由,对聚合无约束力 - 在 Ops Manager 或 Cloud Manager 中,确认主节点的
storage.wiredTiger.engineConfig.cacheSizeGB足够(建议 ≥ 聚合数据集预估体积的 1.5 倍),否则即使允许磁盘,WiredTiger 仍可能因内存不足提前 OOM
注意:allowDiskUse:true 在从节点上永远无效,别试配置文件或启动参数
有人尝试在从节点的 mongod.conf 里加 setParameter: { allowDiskUseForAggregation: true } 或修改 systemLog.verbosity,这些全是徒劳。MongoDB 源码中该标志位仅在 isPrimary() 为真时才参与判断,从节点进程启动即锁定不可变状态。最易被忽略的一点是:**日志里不会报错“allowDiskUse not allowed”,而是在执行阶段静默降级为内存模式,然后触发 QueryExceededMemoryLimitNoDiskUseAllowed 错误**——这个错误码本身就在暗示:不是你没开权限,是节点类型根本不支持。











