ORA-27102报错主因常是HugePages未正确配置,而非内存不足;需检查/proc/meminfo中HugePages_Total是否足够、sysctl -p是否执行、memlock限制是否放开,并用hugepages_settings.sh计算页数,RAC环境须确保各节点参数完全一致。
Oracle启动报ORA-27102: out of memory,但系统内存充足?先查HugePages是否被禁用
很多dba看到这个错误第一反应是加sga,其实更可能是linux内核没分配足够大页。oracle在启用use_large_pages=only时,会拒绝使用普通页,哪怕物理内存还有几十g空闲,也会直接报错退出。
检查方法很简单:
grep Huge /proc/meminfo看
HugePages_Total是否为0,或者远小于sga_max_size(单位KB需换算)。常见坑是:管理员改了/etc/sysctl.conf但忘了执行sysctl -p,或重启后没重载配置。
-
vm.nr_hugepages必须在Oracle实例启动前设置好,动态调整只对后续新分配有效,已运行实例不感知 - 若用
systemd管理Oracle服务,要确认LimitMEMLOCK设为infinity,否则oracle用户无法锁定大页 - 不要把
HugePages_Total设得比SGA还小——Oracle会按sga_max_size向上取整到最近的2MB倍数,留1–2页余量更稳妥
计算vm.nr_hugepages值时,为什么不能直接用sga_max_size / 2048?
因为Oracle实际占用的大页数取决于几个隐藏因素:共享池、Java池、大池都算在SGA里,但某些组件(比如ASMM自动内存管理下的memory_target)可能额外申请页;更关键的是,Linux大页大小默认2MB,但部分内核支持1GB大页,而Oracle 19c+才真正稳定支持1GB页,老版本硬配会失败。
安全做法是用Oracle官方脚本hugepages_settings.sh($ORACLE_HOME/rdbms/admin/下),它会读取当前实例的sga_max_size和pga_aggregate_target,再加固定开销(约10–20MB)后向上取整。
- 手动计算时,把
sga_max_size单位转成KB,除以2048,再+2(预留页) - 如果启用了
use_large_pages=auto,Oracle会尝试混合使用大页和普通页,但日志里会出现WARNING: Large page allocation failed,性能不稳定 - 注意
memlock限制:/etc/security/limits.conf中oracle soft memlock和hard memlock都要设为unlimited或至少大于SGA大小(单位KB)
启用HugePages后Oracle进程RSS突然飙升,top显示内存占用翻倍?
这不是泄漏,是正常现象。开启大页后,Oracle不再通过mmap()按需分配,而是启动时就锁定全部SGA对应的大页,ps和top的RSS列会显示完整占用,不像普通页那样“虚高”。但free -h里的Used不会立刻涨——大页内存不计入常规内存统计,而是单独列在HugePages_Free里。
验证是否生效:连接数据库后查v$sgainfo,看Granule Size是否变成2097152(即2MB);或者用pmap -x <pid> | grep "large"</pid>确认进程地址空间里有大量2MB块。
- 别用
htop看大页使用——它默认不显示大页映射,容易误判 - 如果
HugePages_Free长期为0,说明其他进程(如PostgreSQL、DPDK应用)也在争抢大页,需协调分配 - 重启数据库前记得
echo 0 > /proc/sys/vm/nr_hugepages清空,否则下次分配可能失败
Oracle 12c RAC环境下配置HugePages,节点间参数必须完全一致吗?
必须。RAC所有节点的vm.nr_hugepages值、use_large_pages参数、甚至内核大页大小(cat /proc/sys/vm/hugetlb_page_size)都要相同。否则实例启动顺序稍有变化,先起来的节点占光大页,后起的节点就会报ORA-27102,集群无法收敛。
更隐蔽的问题是:不同节点OS补丁级别不同,可能导致hugetlb_shm_group行为不一致,某节点允许oinstall组访问大页,另一节点拒绝,结果crsctl start res ora.asm卡住。
- 用
cluvfy comp mem -n all提前校验各节点大页配置一致性 - RAC中不要用
use_large_pages=only,推荐use_large_pages=TRUE,允许回退到普通页,避免单点配置失误导致全集群瘫痪 - 修改
/etc/sysctl.conf后,在所有节点执行sysctl -p && systemctl restart oracle-rdbms(或对应服务名)











