前言:上一期《一次一波三折的节点重启问题分析》中提到hugepage配置错误导致系统内存不足引发的问题,许多读者希望了解hugepage的配置方法,这里笔者以oracle使用的视角对Linux中的hugepage做个简单的介绍;希望对大家有所帮助。
01
基本概念
对于linux系统,内存会被分配成4K大小的页面,之后通过不同类型的页面表(PageTable)来进行管理。对于32位的Linux系统,内存的最大寻址范围是0—4G(2的32次方),意味着页面表大概需要100万个元素来管理这些内存,而对于64位的系统,这个页面表的尺寸会变得更大,这对于管理内存来说会产生更大的开销;
本文的主要目的是从数据库的角度来阐述如何通过hugepage 来获得更好地性能,而不是一篇Linux的技术文档,所以对于内存管理的内容(例如页面表的分层结构等)不会进行讨论。

所以,如果能够把内存页面的尺寸放大,就可以更好的管理系统中的内存资源。从2.4 版本的内核开始,Linux系统开始提供hugepage 的功能,允许内存的页面尺寸可以被设置成为2M—256M之间的值。当然,这要求物理内存页面要连续,也就是说,修改hugepage的设置是需要重新启动OS才能够生效的。由于hugepage 和默认的内存页面大小不同,所以他是不能够被swap到磁盘的,换句话说,后台进程kswapd进程会忽略掉hugepage页面。而应用程序需要支持hugepage 特性才能够使用hugepage 中的内存页面。
配置hugepage 页面,需要设置以下的内核参数(针对2.6 版本的内核):
vm.nr_hugepages = <hugepage 的页面个数>
下面的命令可以查看当前的hugepage使用状况
root@orlx52db01 ~]# cat proc/meminfo |grep Huge
HugePages_Total: 13287 <<<< 系统设置的hugepage 页面总数
HugePages_Free: 2 <<< 可用的hugepage 页面总数
HugePages_Rsvd: 0
HugePages_Surp: 0
Hugepagesize: 2048 kB <<<< hugepage页面的尺寸
02
数据库为什么要使用hugepage
由于Oracle数据库会将运行过的SQL 语句和数据缓存到SGA中,成为一个共享内存段,之后很多的服务器进程(serverprocess)会访问SGA中的数据。随着数据库容量的不断增大,应用程序越来越复杂, SGA的尺寸也在不断变大,很多数据库的SGA都超过了100G。 这意味着SGA这个共享内存段的尺寸会很大,一个服务器进程需要运行SQL语句并访问一些数据的时候,就需要在很大的SGA共享内存段当中查找自己需要的数据,如果使用默认的页面大小就会对性能产生影响。所以,对于大部分的Linux系统,如果上面运行的数据库的SGA尺寸比较大的情况下,都建议配置hugepage, Exadata系统也是如此。
只有SGA的内存是会被分配到hugepage当中,PGA是不会的。而且hugepage和oracle 的AMM(自动内存管理)特性是不能兼容的,也就是说如果决定使用hugepage来保存sga的话,就不能够设置MEMORY_TARGET/ MEMORY_MAX_TARGET 参数。

03
关于如何计算需要使用的hugepage页面个数
由于很多数据库服务器上会运行着多个数据库, Oracle在MOS文档401749.1 中给出了一个计算hugepage 页面个数的脚本,下面我们来分析一下这个脚本。
# Check for the kernel version
KERN=`uname -r | awk -F. '{ printf("%d.%d\n",$1,$2);}'` <<< 查看kernel版本
# Find out the HugePage size
HPG_SZ=`grep Hugepagesize proc/meminfo | awk'{print $2}'` <<< 查看hugepage 页面的大小
if [ -z "$HPG_SZ" ];then
echo "The hugepages may notbe supported in the system where the script is being executed."
exit 1
fi
for SEG_BYTES in `ipcs -m | cut -c44-300 | awk'{print $1}' | grep "[0-9][0-9]*"` <<< 通过ipcs 命令找到oracle 数据库所使用的共享内存段,并输出它们的大小
do
MIN_PG=`echo"$SEG_BYTES/($HPG_SZ*1024)" | bc -q` <<<< 计算每个共享内存段需要的hugepage页面数量的最小值
if [ $MIN_PG -gt 0 ]; then
NUM_PG=`echo "$NUM_PG+$MIN_PG+1" | bc -q` <<< 累加页面数量
fi
done
RES_BYTES=`echo "$NUM_PG * $HPG_SZ *1024" | bc -q` <<< 计算所需的hugepage 的大小
……
if [ $RES_BYTES -lt 100000000 ]; then <<<< 如果所有hugepage页面的总和小于100M的话,报错
echo"***********"
echo "** ERROR**"
echo"***********"
echo "Sorry! There arenot enough total of shared memory segments allocated for
HugePages configuration. HugePages can only beused for shared memory segments
that you can list by command:
# ipcs -m
of a size that can match an Oracle DatabaseSGA. Please make sure that:
* Oracle Database instance is up and running
* Oracle Database 11g Automatic MemoryManagement (AMM) is not configured"
exit 1
fi
case $KERN in <<<< 基于不同的内核版本给出需要配置的内核参数
'2.2') echo "Kernelversion $KERN is not supported. Exiting." ;;
'2.4') HUGETLB_POOL=`echo"$NUM_PG*$HPG_SZ/1024" | bc -q`;
echo "Recommended setting: vm.hugetlb_pool = $HUGETLB_POOL" ;;
'2.6') echo"Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
'3.8') echo"Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
'3.10') echo"Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
'4.1') echo"Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
esac
根据上面的分析,这个脚本给出的建议值就是能够包含所有的oracle 数据库的共享内存段(就是SGA)所需要的最少hugepage页面数量的大小。所以,如果服务器上运行的数据库数量和SGA的大小是不变的,那么的确不需要调整hugepage的设置;而如果服务器上的数据库数量或者一些数据库的SGA大小调整之后,是需要重新运行这个脚本来修改hugepage页面数量的。
03
如何让数据库使用hugepage
最后,我们介绍一下如何让数据库实例(ASM实例也同样适用)使用hugepage。
首先,需要将Oracle 用户的memlock 资源限制调大,由于这个限制只是一个目标值,对于大部分的系统,建议调整到比系统所有的物理内存小一点就可以了。例如:对于一个包含了64G内存的系统,可以设置成以下的值。
$ cat etc/security/limits.conf
soft memlock 60397977
hard memlock 60397977
之后,设置数据库参数 USE_LARGE_PAGES = TRUE| ONLY 来指定数据库使用hugepage。以下是这个参数的不同取值的含义:
True:数据库启动时会尝试使用hugepage,但是如果没有配置hugepage或者hugepage的大小不能容纳整个SGA,数据库仍然可以启动。以下是具体的小版本的行为方式:
对于11.2.0.2 版版本的数据库:如果可用的hugepage的大小不能容纳整个SGA,数据库会转而使用普通的内存页面来保存SGA;
对于11.2.0.3 及以上的版本,如果可用的hugepage的大小不能容纳整个SGA,数据库会尝试首先使用尽量多的hugepage来容纳SGA,其他的部分仍然使用普通的内存页面。
Only:数据库只能使用hugepage来保存SGA,如果可用的hugepage页面不能容纳SGA,数据库将无法启动。
False:数据库忽略hugepage,直接使用普通的内存页面来保存SGA。


关注公众号,回复数字查看精彩往期!
回复“017”第十七期:技术人生系列·我和数据中心的故事(第十七期)-看中国最美女DBA的一次价值连城的系统优化!
回复“018”第十八期:技术人生系列·我和数据中心的故事(第十八期)-记一条500行执行计划的SQL问题分析-从应急处理到根因分析
回复“019”第十九期:技术人生系列·我和数据中心的故事(第十九期)-通过案例教你识别操作系统重启是否为CRS引起
回复“020”第二十期:技术人生系列·我和数据中心的故事(第二十期)-ORA-01555错误启示录
回复“021”第二十一期:技术人生系列·我和数据中心的故事(第二十一期)-一条错误结果SQL带来的警示
回复“022”第二十二期:技术人生系列·我和数据中心的故事(第二十二期)-通过trace定位oracle统计信息收集带来的问题
回复“023”第二十三期:技术人生系列·我和数据中心的故事(第二十三期)-致敬618-电子商城秒杀活动技术支持历险记
回复“024”第二十四期:技术人生系列·我和数据中心的故事(第二十四期)-一次一波三折的节点重启问题分析




