必须用oracle官方脚本hugepages_settings.sh在数据库startup状态下以oracle用户执行,路径为$oracle_home/rdbms/install/,输出值需乘1.05向上取整;同时禁用透明大页、amm,并配置memlock unlimited及vm.hugetlb_shm_group等硬性前提,否则ora-27102或大页未被使用。
必须用 oracle 官方脚本 hugepages_settings.sh 在数据库已启动状态下运行,并对输出值加 5% 余量;否则大概率触发 ora-27102: out of memory 或大页完全未被使用。
怎么跑 hugepages_settings.sh 才得到真实可用的数值
这个脚本不是“看看就行”,它读的是当前运行实例的 /proc/<pid>/maps</pid> 和 v$parameter,依赖真实内存布局:
- 必须在数据库实例处于
STARTUP状态下执行(不能是MOUNT或关机) - 路径必须是
$ORACLE_HOME/rdbms/install/hugepages_settings.sh(注意是install/,不是admin/;旧版脚本不兼容 19c) - 必须以
oracle用户执行,且该用户需有读取/proc下进程映射的权限 - 输出里只认这一行:
Recommended setting: vm.nr_hugepages=XXXX,忽略所有说明文字和头部提示 - 示例输出为
vm.nr_hugepages=3140,别直接抄——应设为3297(3140 × 1.05向上取整)
只改 vm.nr_hugepages 为什么 Oracle 还不用大页
常见假象:执行 grep Huge /proc/meminfo 看到 HugePages_Total 有值、HugePages_Free 接近总量,就以为配好了。其实这恰恰说明 Oracle 根本没绑定成功,仍在用普通页。
- 真正有效的信号是:
HugePages_Rsvd > 0且HugePages_Free显著下降(比如只剩个位数) - 缺任意一项都会静默降级:
vm.hugetlb_shm_group = <oinstall_gid></oinstall_gid>(用id -g oinstall查)、kernel.shmmax和kernel.shmall必须 ≥ SGA 实际大小(单位字节 / 页) -
sysctl -p执行后必须检查输出,有 warning 或 error 就得当场解决,不能跳过 - 改完必须重启 Oracle 实例(不是 reload),大页分配只发生在启动瞬间
多实例或混部环境怎么累加 vm.nr_hugepages
一台机器跑 Oracle + MySQL + openGauss?hugepages_settings.sh 只管 Oracle,其他得手动加,但所有服务的大页需求必须在 /etc/sysctl.conf 里一次性配足:
- Oracle 部分:每个实例单独运行脚本,把各实例的推荐值加总(如 3140 + 2860 = 6000)
- MySQL:按
innodb_buffer_pool_size估算,每 2MB 对应 1 页(例如 2GB → +1024 页) - openGauss:重点看
shared_buffers,同样按 2MB/页换算(例如 4GB → +2048 页) - 总和后统一乘 1.05 向上取整,再写入
vm.nr_hugepages - Linux 内核不会动态回收已分配但未使用的
vm.nr_hugepages给新服务,所以不能“先配 Oracle,再加 MySQL”
还有三个容易被忽略的硬性前提
即使数值全对,漏掉下面任何一条,use_large_pages=only 都会失败:
- 必须禁用透明大页(
transparent_hugepage=never),检查路径:/sys/kernel/mm/transparent_hugepage/enabled,输出必须是[never] - 必须禁用 AMM:
memory_target和memory_max_target必须为 0(不能只是设成 0,要确认 SPFILE 中已移除或重置) - 必须放开
memlock:在/etc/security/limits.conf中设* soft memlock unlimited和* hard memlock unlimited,并确认 systemd 的LimitMEMLOCK=infinity已启用











