☰
Oracle HugePages配置实战:从SGA到vm.nr_hugepages
2026/10/10 4:57:09 网站建设 项目流程

简介:面向Linux系统管理员与Oracle数据库运维人员,这份PDF资料系统梳理了在大内存环境下快速启用HugePages的完整流程。内容以RHEL 6.8 + 512GB物理内存、Oracle 11.2.0.4 SGA=400G为测试背景,从设置memlock无限制、修改vm.nr_hugepages参数到运行hugepages_settings.sh脚本获取推荐值,再到更新sysctl并重启,步骤完整且附带命令示例。同时针对ASM实例需使用ASMM、AMM与HugePages不兼容、调整SGA后需重新计算HugePages等关键注意事项做了明确提醒,并提供ipcs -m等验证手段,能帮助读者规避常见配置陷阱。资源为单一PDF文档,体积仅53KB,内容聚焦、查阅方便。已有1704人学习使用,适合需要为Oracle等高性能应用优化内存管理、降低页表开销的系统运维人员参考。

1. HugePages配置:为什么先看SGA再看参数

512GB物理内存的RHEL 6.8,Oracle 11.2.0.4,SGA分配400GB。如果不配HugePages,400GB的SGA意味着大约1亿个页表项,光是页表就要几百MB内存,还要频繁走TLB,甚至被换到swap导致性能崩塌。HugePages的本质是让OS用2MB的连续大页承载SGA,页表项缩到原来的1/512,内存访问效率明显改善。

这套流程在Oracle MOS 401749.1里有理论基础,但实际配置时最卡人的是文件顺序和参数值怎么定。本文按实战顺序走一遍:确认实例状态、改limits.conf解锁memlock、跑脚本算vm.nr_hugepages、验证加踩坑。适合DBA和负责Oracle部署的运维工程师。

2. 前置检查:内核版本、共享内存段与AMM状态

配置HugePages之前,先花三分钟确认三件事:内核版本、Oracle实例是否在运行、以及是否启用了Oracle 11g的AMM。任何一项不符合预期,后面步骤跑了也白跑。这一章按检查顺序把每个命令的输出和判读标准写清楚。

2.1 内核版本决定了脚本输出什么

hugepages_settings.sh脚本会根据内核版本输出不同的推荐参数名。在2.2.x内核上输出的是vm.hugetlb_pool,在2.4以后的内核上输出的是vm.nr_hugepages。RHEL 6.8的内核是2.6.32,走的是vm.nr_hugepages分支。你不需要记住这个映射关系,脚本里的case语句会自动判断,但理解这一点有助于读懂脚本输出:

内核版本脚本输出参数
2.2不支持,直接退出
2.4vm.hugetlb_pool
2.6 / 3.8 / 3.10 / 4.1vm.nr_hugepages

确认内核版本用uname -r:

uname -r

输出类似2.6.32-642.el6.x86_64。脚本会用awk -F.取前两段,得到2.6,然后进入vm.nr_hugepages分支。这里有个实际经验:如果你用的是定制内核,uname -r的输出格式可能不是标准三段式,脚本解析出来的版本号会不准确。我在一个CentOS 6改过的内核上遇到过uname -r输出2.6.32-431.23.3.el6.x86_64,awk取前两段后还是2.6,没问题;但如果内核版本带字母后缀,比如4.1.15-rt17,awk取到的还是4.1,所以目前看脚本的解析逻辑足够健壮。

2.2 Oracle实例必须已经启动

这一条最容易忽略。脚本的核心逻辑是:枚举系统上所有共享内存段,把每个段的大小除以HugePagesize,向上取整后累加,得出需要多少个HugePages。如果数据库没起来,系统里根本没有对应SGA大小的共享内存段,脚本会直接报错:

************* ERROR ************* Sorry! There are not enough total of shared memory segments allocated for HugePages configuration.

这个报错信息已经写得很直白,但很多人第一次看到会误以为是脚本有问题。其实原因只有一个:实例没启动,或者共享内存段不属于你预期的Oracle实例。检查共享内存段的命令是:

ipcs -m

看到类似下面的输出就说明Oracle实例起来了:

------ Shared Memory Segments -------- key shmid owner perms bytes nattch status 0x00000000 32768 oracle 600 429496729600 56 0x00000000 32769 oracle 600 429496729600 56

注意bytes列的单位是字节,400GB的SGA对应大约429496729600字节。实际输出里可能有多个共享内存段,取决于Oracle的共享内存分配方式。只要这些段存在,脚本就能算出正确的推荐值。另外注意perms列,如果共享内存段属于root而不是oracle,说明环境变量ORACLE_SID没设置正确,或者实例不是用oracle用户启动的。脚本里没有检查owner,如果混入了其他进程的共享内存段,计算值会偏大,不会偏小,这点在多个实例或者ASM存在时需要留意。

2.3 AMM必须关闭

Oracle 11g的AMM(Automatic Memory Management)依赖/dev/shm来动态调整SGA和PGA,但HugePages管理的内存不在/dev/shm路径下,两者天然冲突。如果数据库以AMM模式启动,共享内存段不会以常规方式出现在ipcs -m输出里,脚本算出来的值也不具备参考意义。

检查是否启用了AMM,用SQL*Plus登录数据库执行:

show parameter memory_target; show parameter sga_target;
  • 如果memory_target大于0,说明启用了AMM,必须关闭。
  • 如果memory_target为0、sga_target大于0,说明走的是ASMM,可以和HugePages共存。

关闭AMM的操作是把memory_target和memory_max_target设为0,然后重启实例。注意这个操作必须在数据库处于关闭状态时修改spfile参数,否则会报ORA-32016错误。我一般先在pfile里设置,再用create spfile from pfile的方式重建spfile,确保参数可靠落地。具体来说:

alter system set memory_target=0 scope=spfile; alter system set memory_max_target=0 scope=spfile; alter system set sga_target=400G scope=spfile; alter system set pga_aggregate_target=40G scope=spfile; shutdown immediate; startup;

这里sga_target和pga_aggregate_target的值要根据实际业务配置。sga_target设成400G意味着数据库启动后SGA直接分配400G,如果系统物理内存只有512G,SGA加上PGA和其他进程的内存占用,总量可能接近物理上限,需要预留操作系统本身和其他进程的内存余量。HugePages场景下,SGA全都落在大页上,这部分内存不受普通内存管理影响,但PGA仍然走普通内存池,所以pga_aggregate_target不能设得太激进。

2.4 确认HugePagesize

脚本里的HPG_SZ变量来自/proc/meminfo的Hugepagesize字段,x86_64架构下默认是2048KB,也就是2MB。脚本用这个值和共享内存段的字节数做除法,得出需要的页数。跑脚本之前可以看一眼:

grep Hugepagesize /proc/meminfo

输出2048 kB就是正常值。如果输出0或者根本没这个字段,说明内核编译时没启用CONFIG_HUGETLBFS,HugePages没法用,得先确认内核支持再继续。还有一点:arm64架构上Hugepagesize可能是64KB,这种情况下2MB大页不支持,脚本里Hugepagesize*1024的换算逻辑依然是正确的,但你要确认Oracle是否支持该架构的HugePages组合,这属于平台兼容性问题,不在脚本逻辑范围内。

2.5 前置检查的常见误区

不少人觉得前置检查无所谓,直接跳过去跑脚本。根据我的经验,省掉这几步会带来两类麻烦:一是脚本报错后反复排查才想起实例没起,浪费时间;二是AMM没关闭,配置完HugePages后数据库完全没用上大页,生产环境大改返工。把前置检查当流程走,能省掉后面90%的排查时间。

另外,前置检查阶段最好用nmon或者sar记录一下系统的内存基线。配置HugePages前后对比内存的使用情况,能直观看到大页是否真的被数据库使用,也能在排查问题时多一个数据维度。很多DBA习惯只在alert日志里看大页信息,但alert日志只反映数据库视角的内存使用,系统视角的/proc/meminfo才是内核真正分配了多少大页的权威数据,两者要结合起来看。

3. 设置memlock无限制:limits.conf的修改与验证

Oracle官方文档和MOS 401749.1都强调,HugePages要生效,进程必须能锁定内存。这里的锁内存不是数据库自己做mlock调用,而是指Linux的rlimit中memlock这项限制。如果不把memlock调到unlimited,即使系统配置了足够的HugePages,Oracle实例在启动时也可能因为无法锁定大页内存而报错或降级。

3.1 limits.conf文件怎么改

limits.conf是PAM模块pam_limits.so读取的配置文件,作用于通过登录方式启动的进程。对Oracle用户来说,需要设置soft和hard两个memlock值。vi编辑/etc/security/limits.conf,在文件末尾追加两行:

vi /etc/security/limits.conf

追加内容:

oracle soft memlock unlimited oracle hard memlock unlimited

soft是软限制,hard是硬限制。进程可以自行把软限制提升到硬限制以内,但无法超过硬限制。把两个都设为unlimited,能确保Oracle进程无论以什么方式启动,memlock都不会成为瓶颈。这里要区分nofile和memlock:nofile限制的是文件描述符数量,memlock限制的是锁定内存的上限。Oracle安装文档要求nofile通常设成65536或更大,而memlock必须设成unlimited。两个参数都写在同一个文件里,但作用机制完全不同,别搞混。

3.2 配合limits.d目录使用

RHEL 6.8等较老系统上,/etc/security/limits.conf和/etc/security/limits.d/目录都会在登录时被PAM读取。limits.d里如果存在90-nofile.conf之类的文件,系统会先加载limits.conf,再加载limits.d下的文件,后加载的配置会覆盖先加载的。所以如果limits.d里也有oracle用户的memlock设置,需要在limits.conf和limits.d里都检查一遍,避免后加载的配置把unlimited改成其他值。

我在一次RHEL 7迁移中遇到过这种情况:limits.conf里设了unlimited,但limits.d/90-oracle.conf里有memlock 134217728,登录后ulimit -l显示128MB,排查了半天才发现是limits.d里的配置覆盖了。Oracle官方安装文档要求的memlock是unlimited,不是某个具体MB值,这一点在安全基线比较严格的企业环境里特别容易被改掉。

3.3 memlock生效验证

修改limits.conf后,重新ssh登录,或者至少执行一次newgrp触发PAM重新解析,然后验证:

su - oracle ulimit -l

输出unlimited就说明设置成功了。如果输出一个数字或者65536,说明要么limits.conf没写对,要么当前会话没有重新加载PAM配置。从ssh重新登录一次再验证,一般就能解决。如果重新登录还是不行,检查/etc/pam.d/login和/etc/pam.d/sshd里是否配置了pam_limits.so:

session required pam_limits.so

有些精简系统默认不启用这一行,PAM不会读取limits.conf,所有memlock设置全部失效。这是从别人交接过来的服务器上最容易遇到的坑。

3.4 memlock与HugePages的关系

理解了memlock的作用,就能明白为什么HugePages必须配memlock unlimited:Oracle在启动时要把SGA映射到大页内存上,这个映射操作需要锁定内存,而锁定的上限就是memlock。如果memlock太小,SGA映射会失败,数据库会从HugePages降级到普通内存页,alert日志里Large Pages Information的Total Shared Global Region in Large Pages这一行就会小于SGA大小,甚至为0。

还有一个细节:memlock是per-process的限制,不是系统级别的。512GB物理内存的机器上,memlock设为unlimited不会带来安全问题,因为HugePages本身受vm.nr_hugepages控制,就算进程把内存锁到爆,锁的总量也受限于大页总数。所以把memlock设成unlimited是安全的。反过来,如果memlock设置成某个固定值,比如16GB,而SGA是400GB,Oracle启动时最多只能锁定16GB的大页,SGA的剩余部分会落到普通内存页上。这种情况下数据库不会报错,但HugePages只覆盖了SGA的一小部分,alert日志里Total Shared Global Region in Large Pages会显示为16GB而不是400GB,性能提升大打折扣。

3.5 何时重启系统

修改limits.conf后不需要重启系统,重新登录即可生效。但修改vm.nr_hugepages之后,需要sysctl -p让内核参数生效,而HugePages的分配要求系统有足够的连续内存,如果物理内存碎片化严重,sysctl -p之后HugePages_Total可能小于vm.nr_hugepages的设定值。这种情况下,reboot可能是最省事的解决方式。重启后内核在早期阶段分配大页,此时内存尚未被各个进程瓜分,连续大页的分配成功率比运行中的系统高得多。

RHEL 6.8的默认行为是系统启动时按sysctl.conf里的vm.nr_hugepages值分配大页。如果你担心分配失败,可以在/etc/rc.local里加一条echo 204805 > /proc/sys/vm/nr_hugepages,让系统在启动后期再尝试一次。这个方法在第5章的避坑部分会详述。

3.6 memlock与Oracle安装文档的联动

Oracle 11g的官方安装文档对用户资源限制有一套完整的建议值,除了memlock之外,还有nproc(最大进程数)、nofile(最大文件描述符数)、stack(栈大小)。这些参数都写在limits.conf里,配置HugePages时顺手检查一遍,避免数据库在运行中出现其他资源问题:

参数建议值
memlockunlimited
nofile65536
nproc2048或更高
stack10240 KB

在limits.conf里设置stack时要小心,stack设得太大可能导致每个进程的虚拟内存空间膨胀。Oracle 11.2要求stack soft和hard都设为10240KB,但如果系统里同时跑着其他应用,这个值可能需要调整。HugePages配置本身不依赖stack参数,但数据库运行过程中如果出现ORA-600或者进程无法创建,nproc和nofile是优先排查项。既然已经动limits.conf了,把这一组参数一并配好,省得后面单独再改。

4. 脚本计算与sysctl落地:从hugepages_settings.sh到vm.nr_hugepages

前置检查和memlock配置都到位后,接下来是核心步骤:跑官方脚本算出推荐值,写进sysctl.conf,让它生效。这一章把脚本原理、三种输出场景、落地方法和验证串起来讲。

4.1 脚本是怎么算的

hugepages_settings.sh是MOS 401749.1提供的计算脚本。它的计算逻辑是:枚举ipcs -m输出里的所有共享内存段,把每个段的字节数除以HugePagesize(脚本把/proc/meminfo里的2048 kB换算成字节),向上取整再加1,然后累加。加1的目的是留余量,避免某个段恰好落在页边界上导致空间不够。脚本开头有一个read命令,需要按回车才会继续执行,这是为了方便显示欢迎信息,执行时注意别卡在这一步。

脚本核心循环这段值得细看:

for SEG_BYTES in `ipcs -m | cut -c44-300 | awk '{print $1}' | grep "[0-9][0-9]*"` do MIN_PG=`echo "$SEG_BYTES/($HPG_SZ*1024)" | bc -q` if [ $MIN_PG -gt 0 ]; then NUM_PG=`echo "$NUM_PG+$MIN_PG+1" | bc -q` fi done

这段代码从ipcs -m输出里取出共享内存段的字节数,除以HugePagesize得到每个段需要的最小大页数,累加并额外加1。bc命令做浮点运算,除法的商是整数部分,+1是保证每个段至少多预留一页。这里的cut -c44-300是按字符位置截取ipcs -m的输出列,因为不同Linux发行版上ipcs -m的空格对齐方式不完全一致,字符位置截取比awk按列分割更稳。如果你在自己系统上测试时发现脚本读不到数据,先用ipcs -m | cut -c44-300看输出是不是全为空,如果是,说明发行版的ipcs输出列偏移有差异,这是脚本在非Oracle Linux发行版上常见的兼容性问题。

4.2 三种场景下的输出解读

第一种是实例已经启动且SGA_MAX_SIZE=12G的场景,脚本输出:

Recommended setting: vm.nr_hugepages = 6148

6148这个数字怎么来的?12GB除以2MB大约等于6144,再加上脚本对每个段的+1余量,4个段多出4页,就得到6148。这种小SGA场景下,手算和脚本算出来的差别基本就在几个页之内。

第二种是本文实际场景,SGA_MAX_SIZE=400G:

Recommended setting: vm.nr_hugepages = 204805

400GB除以2MB等于204800,加上脚本的余量就是204805。这里有个现象值得注意:400GB正好对应204800个2MB页面,脚本多算了5页。这5页就是安全余量,用来覆盖共享内存段的边界溢出。实际部署时,这个余量几乎不会导致内存浪费,204805页乘以2MB大约是400.01GB,相对400GB的SGA可以忽略不计。

第三种是实例没有启动:

************* ERROR ************* Sorry! There are not enough total of shared memory segments allocated for HugePages configuration.

这个报错在2.2节已经解释过了:没有共享内存段可算。遇到这个报错,先启动数据库,再跑脚本。注意报错信息里的“Please make sure that: Oracle Database instance is up and running”这一句,以及“Oracle Database 11g Automatic Memory Management (AMM) is not configured”,这两句把最常见的原因都写在里面了。报错不是脚本坏了,是环境没满足脚本的前置条件。

4.3 把推荐值写入sysctl.conf

拿到推荐值之后,把它写进/etc/sysctl.conf:

vi /etc/sysctl.conf

追加一行:

vm.nr_hugepages = 204805

然后执行sysctl -p让配置生效:

sysctl -p

sysctl -p会按顺序加载sysctl.conf里的所有参数。如果系统里已经有vm.nr_hugepages的旧值,需要先把旧值删掉再追加,避免重复定义。我习惯在修改之前先grep一下:

grep nr_hugepages /etc/sysctl.conf

如果输出里有旧的配置项,用sed或者vi删掉再写新的。sysctl -p执行后,用sysctl vm.nr_hugepages确认当前生效值:

sysctl vm.nr_hugepages

输出vm.nr_hugepages = 204805说明参数生效。如果输出和sysctl.conf里的值不一致,说明系统里还有其他地方设置了vm.nr_hugepages,比如/etc/sysctl.d/目录下的文件。RHEL 6.8默认读取/etc/sysctl.conf,但如果你装了调优工具tuned,它可能动态调整内核参数并覆盖静态配置。

注意:修改sysctl.conf之前先用grep确认旧值,避免同一参数重复定义导致sysctl -p报错。

4.4 生效后检查HugePages总量

sysctl -p执行成功后,检查/proc/meminfo里的HugePages_Total:

grep Huge /proc/meminfo

如果输出HugePages_Total等于204805,说明大页已经分配成功。如果小于204805,比如只有180000,说明系统内存碎片化,连续物理内存不够分配这么多2MB页面。这时可以尝试触发内存规整:

echo 1 > /proc/sys/vm/compact_memory

然后再看HugePages_Total有没有涨。如果还是没有达到目标值,重启系统是更稳妥的解决方式。内核在启动阶段分配大页时,物理内存还没有被大量进程占用,拿到连续内存的成功率远高于运行中的系统。

4.5 脚本的其他用法

hugepages_settings.sh除了计算vm.nr_hugepages之外,还可以用来验证当前配置是否合理。比如数据库SGA从400G调小到300G,可以先跑脚本看新推荐值,对比当前vm.nr_hugepages。如果当前值比新推荐值大很多,说明有大量HugePages处于空闲状态,这些内存被大页池占着,普通进程无法使用,属于浪费;反过来,如果当前值比新推荐值小,说明大页不够用,数据库可能已经把部分SGA放到普通内存页上。这个脚本是个很好的体检工具,每次调整SGA大小后跑一遍,比手动算页数靠谱得多。

5. 避坑指南:AMM不兼容、SGA调整与重启丢配置

HugePages配置本身不难,难的是配置之后系统表现不符合预期。这一章把实际遇到过的几个坑按现象、原因、解决三步写出来,方便对照排查。每一条都是真实发生过的问题,不是理论推演。

5.1 配置了HugePages,但alert日志显示Large Pages为0

现象:按步骤配置完vm.nr_hugepages并重启数据库,alert日志里Large Pages Information一栏显示Total Shared Global Region in Large Pages = 0 GB,数据库完全没用上大页。

原因:数据库启用了Oracle 11g的AMM。memory_target参数非零时,SGA和PGA统一由AMM管理,内存分配走/dev/shm映射,不会使用HugePages。这是Oracle 11g和HugePages的已知兼容性问题,MOS 749851.1专门解释过。

解决:关闭AMM。用SQL*Plus执行:

alter system set memory_target=0 scope=spfile; alter system set memory_max_target=0 scope=spfile; alter system set sga_target=400G scope=spfile; alter system set pga_aggregate_target=40G scope=spfile;

然后重启实例。重启后再次查看alert日志,Large Pages Information里Total Shared Global Region in Large Pages应该变成400 GB。注意修改顺序:memory_target和memory_max_target要先于sga_target设置,避免Oracle在中间状态把SGA撑到异常大小。如果直接在数据库open状态下执行alter system,某些参数会立即对当前实例生效,导致和HugePages配置打架的现象更混乱,所以scope=spfile加上重启是最稳妥的路径。

5.2 调整SGA大小后,HugePages失效

现象:数据库SGA从300G调到400G,重启后实例能起来,但alert日志显示Large Pages用了0,系统HugePages_Total还是300G对应的值。

原因:vm.nr_hugepages是静态分配的。SGA从300G涨到400G,需要更多大页,但系统里分配好的大页数量还是按300G配的,新SGA塞不进现有的大页池,Oracle只能降级用普通内存页。

解决:调整SGA后,把vm.nr_hugepages先改为0释放大页,重启数据库让新SGA完全用普通页启动,然后重新跑hugepages_settings.sh脚本,拿到新推荐值,再改vm.nr_hugepages并重启。MOS 401749.1的脚本注释里也明确写了这个步骤。这是SGA变更后的标准动作,每次改SGA都强制自己走一遍,不跳过。

5.3 系统重启后HugePages_Total变成0

现象:重启服务器后,/proc/meminfo里HugePages_Total=0,但/etc/sysctl.conf里明明配了vm.nr_hugepages=204805。

原因:HugePages在系统启动早期分配,vm.nr_hugepages的生效顺序在其他内存子系统初始化之后。如果物理内存碎片化严重,内核可能在启动时无法一次性分配204805个连续大页,于是一部分分配失败,HugePages_Total就低于期望值甚至为0。

解决:在/etc/rc.d/rc.local里加一条延迟分配命令:

echo 204805 > /proc/sys/vm/nr_hugepages

rc.local在系统启动接近完成时执行,此时内存布局已经稳定,分配成功率更高。另外,如果是虚拟机环境,检查宿主机是否预留了足够内存。内存超分会导致guest内部分配大页失败,这个坑在云主机上尤其常见。我在一个OpenStack环境里遇到过,宿主机内存超分1:4,guest配置了vm.nr_hugepages后反复重启,HugePages_Total总是低于目标值,最后检查宿主机的调度策略才定位到问题。物理机上出现同样现象的概率低得多,但仍不能排除NUMA拓扑的影响。

5.4 多个Oracle实例时脚本结果不准确

现象:服务器上跑着两个Oracle实例,SGA各200G,脚本给出的推荐值大于400G对应的页数。

原因:脚本会统计系统上所有的共享内存段,包括ASM实例的共享内存段。ASM实例也需要共享内存,如果ASM实例的共享内存段被计入,推荐值会偏大。另外,脚本不区分共享内存段的所有者,如果系统里还有非Oracle的应用程序使用共享内存,比如PostgreSQL,它的共享内存段也会被算进去。

解决:为ASM实例配置ASMM,关闭AMM,确保ipcs -m列出的共享内存段都来自你预期纳入计算的Oracle实例。脚本注释里有一句For ASM instance, it needs to configure ASMM instead of AMM,说的就是这个问题。如果系统里还有其他使用共享内存的应用,算完推荐值之后手动减去这部分段对应的页数。注意,这里的减是要谨慎的,只有在确定非Oracle的共享内存段不会随着数据库启动消失时才这么干。

5.5 rc.local失效

现象:在rc.local里加了echo命令,但重启后HugePages_Total还是0,rc.local好像没执行。

原因:CentOS 7/RHEL 7以后,rc.local需要可执行权限才能运行。RHEL 6.8上默认是可执行的,但也可能被安全加固脚本改掉权限。如果你的系统是按照等保或者企业安全基线做了加固,rc.local的可执行权限可能被收掉了。

解决:检查权限并确保脚本内容正确:

chmod +x /etc/rc.d/rc.local cat /etc/rc.local

另外,rc.local里的命令最好加上日志输出,方便排查:

echo 204805 > /proc/sys/vm/nr_hugepages && echo "$(date) hugepages set" >> /var/log/hugepages.log

这样即使重启后大页没分配成功,也能通过日志确认rc.local是否执行了。

5.6 关了大页后普通内存页不够用

现象:把vm.nr_hugepages改回0释放大页后,系统可用内存反而变少了,free命令看到的available内存明显下降。

原因:HugePages池本质上是预分配内存。释放HugePages时,这些内存并不会马上回到普通内存池,要等内核把大页拆回标准页。这个过程可能需要几分钟,如果系统内存压力大,free看到的可用内存会暂时偏低。

解决:不需要额外操作,等一段时间或者执行sync加drop_caches加速回收。注意不要在生产环境随意执行drop_caches,有性能风险。我看到有的同事在把HugePages改回0之后紧接着启动一堆应用,结果因为可用内存还没恢复导致OOM,这属于对HugePages释放机制不了解导致的误伤。改完参数之后观察5到10分钟,等大页回收到普通内存池再继续后面的操作。

6. 验证配置:/proc/meminfo与alert日志的完整检查

配置完HugePages后,验证不能只看一个指标。我的习惯是同步检查系统层和数据库层两个维度的证据,确保HugePages真的被用上了。

6.1 系统层验证:/proc/meminfo

grep Huge /proc/meminfo

输出示例:

AnonHugePages: 0 kB HugePages_Total: 204805 HugePages_Free: 168475 HugePages_Rsvd: 168471 HugePages_Surp: 0 Hugepagesize: 2048 kB

这几个字段的含义:HugePages_Total是系统分配的大页总数,应该等于vm.nr_hugepages设置值;HugePages_Free是尚未使用的大页数;HugePages_Rsvd是已经预留但还没实际映射的大页数,Oracle实例启动时会有一部分页面处于reserved状态;HugePages_Surp是超过vm.nr_hugepages设置值之外的surplus大页数量,正常应该为0;Hugepagesize是大页大小,x86_64下是2048 kB。

6.2 数据库层验证:alert日志

数据库启动时,alert日志中会有如下内容:

************************ Large Pages Information ******************* Per process system memlock (soft) limit = UNLIMITED Total Shared Global Region in Large Pages = 400 GB (100%) Large Pages used by this instance: 204801 (400 GB) Large Pages unused system wide = 4 (8192 KB) Large Pages configured system wide = 204805 (400 GB) Large Page size = 2048 KB ********************************************************************

关键看两行:Total Shared Global Region in Large Pages = 400 GB (100%)表示SGA完全落在大页上,memlock (soft) limit = UNLIMITED表示memlock生效。如果这两行中任何一行不是预期值,回头检查第2章的AMM状态和memlock设置。

6.3 从free到alert的完整对照

/proc/meminfo给出的HugePages_Total是系统视角,alert日志给出的Large Pages configured system wide是数据库视角。两者数值应当一致,都是204805。如果系统层配置正确但数据库层显示为0%,问题大概率出在memlock或者AMM。从那以后我每次配置HugePages都强制走一遍这两个维度的验证,两边对上了才算完成,希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询