必须用oracle官方脚本hugepages_settings.sh在数据库已启动状态下运行并加5%余量,否则易因漏计sga保留区、结构对齐及内核取整导致ora-27102或大页未使用。
直接给结论:别手算 vm.nr_hugepages,必须用 oracle 官方脚本 hugepages_settings.sh 在数据库已启动状态下运行,再加 5% 余量;否则大概率出现 ora-27102: out of memory 或大页完全未被使用。
为什么不能用 sga_max_size ÷ 2048 手动计算
看似合理,但实际会漏掉三类开销:
- Oracle SGA 内部保留区(如固定 SGA、日志缓冲区对齐边界)
- 部分内存结构(如某些 latch、shared pool 子结构)仍走普通页,但占用大页槽位
- 内核页对齐强制向上取整到 2MB 边界,哪怕只多 1KB 也要占满一页
实测中,6GB SGA 实际需要约 3120 页(而非 6144÷2=3072),差出 50 页。差这几十页,use_large_pages=only 就直接失败。
怎么跑 hugepages_settings.sh 才有效
这个脚本不是“看看就行”,它依赖当前运行实例的真实内存分配值。常见错误是:实例没启、路径错、权限不足。
- 必须在数据库实例已
STARTUP状态下运行(脚本读/proc/<pid>/maps</pid>和v$parameter) - 路径是
$ORACLE_HOME/rdbms/install/hugepages_settings.sh(注意是install/,不是admin/;旧版脚本不兼容 19c) - 以
oracle用户执行,且该用户需有读取/proc下进程映射的权限 - 输出里找
Recommended setting: vm.nr_hugepages=XXXX这行,不是开头的说明文字
示例输出:
Recommended setting: vm.nr_hugepages=3140
这时别直接抄 3140 —— 建议设为 3297(3140 × 1.05 向上取整)。
多实例或混部环境怎么累加
一台机器跑 Oracle + MySQL + openGauss?hugepages_settings.sh 只管 Oracle,其他得手动加。
- Oracle 部分:用脚本得出值(如 3140)
- MySQL:按
innodb_buffer_pool_size估算,每 2MB 对应 1 页(例如 2GB → +1024 页) - openGauss:重点看
shared_buffers,同样按 2MB/页换算(例如 4GB → +2048 页) - 总和后统一加 5% 余量,再写入
vm.nr_hugepages
关键点:所有服务的大页需求必须在 sysctl.conf 里一次性配足,不能“先配 Oracle,再加 MySQL”——Linux 内核不会动态回收已分配但未使用的 vm.nr_hugepages 给新服务。
改完 sysctl.conf 还要盯哪几件事
只改 vm.nr_hugepages 是最常见翻车点。以下四项缺一不可:
-
vm.hugetlb_shm_group = <code>oinstall组的 GID(用id -g oinstall查,不是组名) -
kernel.shmmax≥ SGA 最大字节数(例如 6GB → 设为6442450944) -
kernel.shmall≥shmmax / 4096(单位是页,不是字节) -
memlock在/etc/security/limits.conf中设为unlimited(soft和hard都要)
改完必须执行 sysctl -p 并确认无报错;然后重启数据库(不是 reload,是 shutdown immediate; startup)。验证时不要只看 HugePages_Free,重点检查 HugePages_Rsvd > 0 且 ps -eo pid,comm,args | grep pmon 输出里有 hugetlb 字样。
最容易被忽略的是:RAC 环境下每个节点的 vm.nr_hugepages 值必须完全一致,哪怕某节点当前只起一个实例——集群心跳和 OCR 访问可能触发额外共享内存段分配,不一致会导致节点驱逐。











