大页内存(HugePages)通过减少TLB miss、锁定物理内存避免swap、压缩页表规模三方面降低CPU内存管理开销,显著提升数据库性能;其效果取决于是否真实存在页表遍历瓶颈、SGA足够大且受TLB或swap干扰,需用perf、/proc/vmstat、vmstat精准诊断,按SGA+开销/2MB向上取整计算数量,并关闭THP、禁用AMM、放开memlock后验证进程级HugetlbPages才生效。

大页内存(HugePages)对数据库性能的提升,不是靠“加内存”或“开个开关”实现的,而是通过减少地址翻译开销、锁定物理内存、规避页表膨胀这三件事,直接降低CPU在内存管理上的无效消耗。评估它是否值得配、配多少、效果是否真实落地,关键看三个维度:CPU瓶颈是否来自页表遍历、SGA/堆外内存是否足够大、以及当前系统是否被TLB miss或swap干扰。
看CPU是否真被页表和TLB拖累
很多DBA一上来就配HugePages,却没确认问题根源。先用这几条命令快速定位:
-
perf top -g 看 top 函数里有没有
__do_page_fault、pte_lookup或tlb_flush—— 这些高频出现,说明地址翻译正在吃CPU -
cat /proc/vmstat | grep pgpgin\|pgpgout\|pgmajfault 中
pgmajfault(主缺页)持续高于每秒100次,尤其在无I/O压力时,大概率是小页导致频繁页表构建 -
vmstat 1 观察
si/so(swap in/out)是否非零 —— 即使内存充足,4KB页也容易因碎片触发swap,而HugePages内存不可交换,能彻底堵住这个口
算准大页数量:别拍脑袋,要扣住SGA+实际占用
HugePages不是越多越好,配多了浪费,配少了不生效。核心公式是:
HugePages数 = ceil( (SGA_MAX_SIZE + Oracle额外开销) / Hugepagesize )
其中:
- Oracle官方推荐用
hugepages_settings.sh脚本自动计算(从Doc ID 401749.1获取),它会扫描当前所有共享内存段,比手动算更准 - PostgreSQL/Redis等需按
shared_buffers + work_mem × max_connections估算总内存需求,再向上取整到2MB边界 - 注意:Hugepagesize通常是2MB(x86_64),可用
getconf PAGE_SIZE和grep Hugepagesize /proc/meminfo双确认
验证是否真在用:不能只看配置,要看进程级证据
写入 /proc/sys/vm/nr_hugepages 后,不代表数据库就在用。必须交叉验证:
-
全局视角:
grep -i huge /proc/meminfo查HugePages_Total、HugePages_Free、HugePages_Rsvd——Rsvd> 0 表示有进程已申请但未映射,Free= 0 不代表全用完,只是暂未分配 -
进程视角:
cat /proc/$(pgrep -f "ora_pmon" | head -1)/smaps | grep -i hugetlb或cat /proc/$(pgrep -f postgres | head -1)/status | grep -i huge—— 输出中HugetlbPages:行数值大于0,才是真用了 -
对比指标:启用前后对比
perf stat -e dTLB-loads,dTLB-load-misses—— dTLB miss ratio 下降30%以上,基本可确认收益显著
绕过常见陷阱:THP、AMM、memlock一个都不能漏
配了HugePages却没效果?大概率掉进这三个坑:
-
透明大页(THP)没关干净:仅改
enabled=never不够,defrag也必须设为never,否则 khugepaged 会抢连续内存,导致 nr_hugepages 分配失败 -
Oracle AMM开着:
MEMORY_TARGET > 0与 HugePages 冲突,必须设为0并重启实例;PostgreSQL 则需确保huge_pages = on且 shared_buffers 已预热 -
memlock限制没放开:Oracle用户必须在
/etc/security/limits.conf中设* soft memlock unlimited,否则启动时报ORA-27123: unable to attach to shared memory segment











