必须调大fs.aio-max-nr,否则io_setup返回EAGAIN,导致Oracle等报ORA-27091/ORA-27090;确认瓶颈需对比cat /proc/sys/fs/aio-nr与aio-max-nr,若接近或相等且日志频现EAGAIN即已达上限。

fs.aio-max-nr 必须调大,否则 io_setup 会直接返回 EAGAIN,数据库或高性能存储服务(如 Oracle、PostgreSQL、RocksDB)可能报 ORA-27091 或 ORA-27090。
怎么确认当前值是否已触发瓶颈
先看两个关键指标:
-
cat /proc/sys/fs/aio-nr:当前已分配的异步 I/O 请求数(活跃上下文总和) -
cat /proc/sys/fs/aio-max-nr:系统允许的最大值
如果 aio-nr 接近甚至等于 aio-max-nr,且应用日志里频繁出现 EAGAIN 或 Unable to reserve kernel resources for asynchronous disk I/O,说明已到上限。注意:aio-nr 不会自动回收,长期运行的服务可能持续累积。
临时修改:快速验证是否有效
执行以下命令立即生效(重启后失效):
echo 1048576 > /proc/sys/fs/aio-max-nr
验证是否写入成功:
cat /proc/sys/fs/aio-max-nr
常见错误:
- 权限不足 → 必须用
root执行 - 写入后数值没变 → 检查是否拼错路径(是
/proc/sys/fs/aio-max-nr,不是aio_max_nr或max-nr) - 写入超大值失败(如 4194304)→ 内核可能因内存紧张拒绝,此时需结合
free -h和dmesg | tail查看是否有kmalloc失败提示
永久生效:避免服务重启后回落
编辑 /etc/sysctl.conf,追加一行:
fs.aio-max-nr = 1048576
然后加载配置:
sysctl -p
注意点:
- 不要用
sysctl.conf里的注释符号#写在行首再跟配置,某些旧版 sysctl 会跳过整行 - 该值不是越大越好:每个 AIO 上下文约占用几 KB 内核内存,设为 4M 可能吃掉百 MB 内存,对小内存机器反而引发 OOM
- 合理估算方式:按 DBWR/IO 线程数 × 2~3 倍。例如 Oracle 实例有 256 个写进程,建议设为 524288~786432;高并发 OLTP 场景可上探至 1048576
为什么改了还是报 ORA-27090
这个错误不单看 fs.aio-max-nr,还要同步检查:
- 用户级限制是否卡住:用
ulimit -n看当前进程打开文件数上限,若低于 65535,io_setup可能因无法分配 eventfd 而失败 - 内核是否真正加载了 AIO 模块:
lsmod | grep aio应有kcma或类似模块(取决于内核版本) - Oracle 参数
disk_asynch_io是否为TRUE(用show parameter disk_asynch_io查),否则即使内核支持也走同步路径 -
/proc/sys/fs/aio-nr长期不降 → 可能有进程泄漏 AIO context,需结合lsof -p $PID | grep eventfd定位
真正起作用的是 aio-nr 与 aio-max-nr 的差值,而不是绝对数值;压测时盯住前者的变化速率,比静态调大更关键。











