直接用sga_max_size除以2MB会出错,因SGA实际分配含保留区、对齐填充等额外开销,真实大页需求多出10~30页,且脚本须在实例启动后运行并累加多实例值。

为什么直接用 sga_max_size 除以 2MB 会出错
很多人一上来就拿 sga_max_size 除以 2097152(2MB 字节数),算出 vm.nr_hugepages 值,结果 Oracle 启动后 HugePages_Rsvd 仍是 0。这是因为:sga_max_size 是逻辑上限,而实际 SGA 分配包含保留区、内存对齐填充、固定结构(如 shared pool 的 chunk header)等额外开销,真实大页需求通常比它多出 10~30 页。
更关键的是:脚本必须在数据库实例已启动状态下运行,否则读不到真实的共享内存段信息。多实例环境必须累加各实例输出值,不能只看主库。
- 必须运行 Oracle 官方脚本:
$ORACLE_HOME/rdbms/install/hugepages_settings.sh(不是admin/下的旧版) - 脚本输出的推荐值是下限,建议在此基础上再 +5% 向上取整(防内核分配微调失败)
- 若输出为
Recommended pages = 6145,应设为6453(6145 × 1.05 ≈ 6452.25 → 取整)
sysctl.conf 里漏掉这三项,use_large_pages=only 就是摆设
只改 vm.nr_hugepages 是最常见翻车点。Oracle 启动时发现其他条件不满足,会静默降级回普通页,grep Huge /proc/meminfo 看起来有页,但 HugePages_Rsvd 为 0 就说明没绑定成功。
-
vm.hugetlb_shm_group = <code>oinstall组的 GID(用id -g oinstall查,不是用户名) -
kernel.shmmax和kernel.shmall必须 ≥ 实际 SGA 总大小(单位:字节 / 页);例如 SGA=12GB,则kernel.shmmax至少设为12884901888,kernel.shmall至少为12884901888 / 4096 ≈ 3145728 - 改完必须执行
sysctl -p,并确认无报错;若有警告(如 “invalid key”),说明某行格式错误或参数名拼错
memlock 设成 unlimited 还不够,systemd 会悄悄覆盖它
在 RHEL/CentOS 7+ 或 Oracle Linux 7+ 上,即使 /etc/security/limits.conf 里写了 * soft memlock unlimited,systemd 也会默认限制 Oracle 进程的 LimitMEMLOCK 为 64KB。结果就是 ulimit -l 显示 unlimited,但 Oracle 启动时仍报 ORA-27102: out of memory。
解决方法是在 systemd service 文件中显式放开:
- 编辑
/usr/lib/systemd/system/oracle-rdbms.service或对应实例服务文件 - 在
[Service]段下添加:LimitMEMLOCK=infinity - 执行
systemctl daemon-reload && systemctl restart oracle-rdbms - 验证:启动后运行
cat /proc/$(pgrep pmon)/limits | grep memlock,确认Max locked memory显示unlimited或极大值
use_large_pages=only 不生效?先看 HugePages_Rsvd 是否 > 0
判断大页是否真被 Oracle 使用,唯一可靠指标是 /proc/meminfo 中的 HugePages_Rsvd。它表示“已被进程预留、尚未分配但保证可用”的大页数。只要这个值大于 0,说明 Oracle 成功绑定了大页;如果为 0,不管 HugePages_Free 多高,都等于没用上。
常见原因排序(按发生频率):
-
use_large_pages参数设为TRUE或FALSE—— 必须是only才强制启用,TRUE仅表示“可选”,遇到 memlock 不足等会自动跳过 - AMM 未彻底禁用:检查
memory_target和memory_max_target是否真为 0(注意:设为 0 可能报 ORA-00843,需用RESET或重建 spfile) -
lock_sga=FALSE(虽非必需,但开启后可进一步确认大页绑定状态) - 节点间配置不一致(RAC 环境下尤其致命):所有节点的
vm.nr_hugepages、memlock、use_large_pages必须完全相同
真正麻烦的不是配置步骤多,而是每个环节都依赖前序环节的精确达成——比如 sysctl -p 报错没处理,后面所有操作都是徒劳;又比如 RAC 中一个节点漏改 vm.hugetlb_shm_group,整个集群可能因脑裂风险拒绝启动。


















