Linux内核支持
linux虽然没有aix,hp unix那么强悍,但linux也是非常优秀的os。为了提升linux的性能,它采用了很多 io、memory的调度机制,linux使用内存的方式是采用vm的方式,即linux把物理内存和swap共同虚拟成可用内存来对外提供使用,有时用户看似使用内存,实则使用磁盘。linux管理内存的单位是页(pages),一般情况下默认的 page size 为4k。显然,对于SGA比较大(SGA_MAX_SIZE > 8G )的数据库系统,管理这么大的内存会给系统造成很大的负担,再加上频繁的pagein/pageout,最终会成为系统的瓶颈。
Hugepages引入
hugepage是在linux2.6内核被引入的,其目的就是使用更大的 memory page size 以适应越来越大的系统内存管理。Page Table是用来存放虚拟内存页和物理内存页映射关系的内存数据结构。当进程访问虚拟内存地址时,首先访问Page Table,然后再根据Page Table的映射关系mapping来访问真实物理内存地址(RAM+SWAP)。
(借用网络上的图示)因为Linux默认的page size为4k,所以相应的 Page Table 内存结构会比较大。而Hugepages的常见page size为2M,是默认值4k的500倍,可以大大降低 Page Table 内存结构的大小。接下来,引用两个例子,比较启用hugepages与否两者之间的区别。
例1:没有配置Hugepage的系统
$stat -f / | grep "Block size" Block size: 4096 Fundamental block size: 4096 首先,先查看系统的block size大小。 $ cat /proc/meminfo MemTotal: 132086880 kB ... PageTables: 4059612 kB 可以看出,系统内存为128G,pagetable大小约为4G。
例2:配置了Hugepage的系统
$ cat /proc/meminfo MemTotal: 98999880 kB PageTables: 79916 kB可以看出:系统内存为96G, PageTable大小仅为78M。 为了提升访问性能,在CPU cache中有一个固定大小的TLB(Transaction Lookaside Buffer),用来保存部分Page Table以提高虚拟地址的转换速度,遵循让数据尽可能的靠近CPU的原则。提高了TBL命中率,也就是提高了地址转换的速度。因为Page size变大了,所以同样大小的TLB,所覆盖的内存大小也变大了。使用Hugepages的内存页是不会被交换出去的,永远常驻在内存中,所以也减少了内存页替换的额外开销
HugePages注意事项
下面再说说在数据库服务器上使用Hugepages要注意的几点1. Hugepages是在分配后就会预留出来的,其大小一定要比服务器上所有实例的SGA总和要大,差一点都不行。比如说Hugepages设置为90G,oracle SGA为91G,那么oracle在启动的时候就不会使用到这90G的Hugepages。这90G就浪费了。所以在设置Hugepages时要计算SGA的大小,后面会给出一个脚本来计算。2. 其他进程无法使用Hugepages的内存,所以不要设置太大,稍稍比SGA大一点保证SGA可以使用到hugepages就好了。3. PGA不会使用Hugepages的内存。所以11g的AMM (Automatic Memory Management,memory_target参数)是不被支持的。而ASMM(Automatic Shared Memory Management, SGA_target参数)是被支持的,这两个不要搞混淆了。4. 在meminfo中和Hugepage相关的有四项
HugePages_Total 所分配的hugepages页面数目,和Hugepagesize相乘后得到所分配的内存大小;
HugePages_Free 从来没有被使用过的Hugepages数目。即使oracle sga已经分配了这部分内存,但是如果没有实际写入,那么看到的还是Free的;
HugePages_Rsvd 已经被分配预留但是还没有使用的page数目。在Oracle刚刚启动时,大部分内存应该都是Reserved并且Free的,随着oracle SGA的使用,Reserved和Free都会不断的降低;
Hugepagesize 默认的hugepages页大小,不可以修改;
HugePages_Free – HugePages_Rsvd 这部分是没有被使用到的内存,如果没有其他的Oracle instance,这部分内存也许永远都不会被使用到,也就是被浪费了。
开启HugePages并使数据库生效
开启大页HugePage步骤如下:1、关闭Oracle Database 11g中的AMM(Automatic Memory Management),即把两个参数MEMORY_TARGET / MEMORY_MAX_TARGET设为0另外:默认情况下ASM instance 也是使用AMM的,但因为ASM 实例不需要大SGA,所以对ASM 实例使用HugePages意义不大。2、计算hugepages的参数值Oracle默认提供hugepages计算脚本(/app/oracle/product/11.2.0/rdbms/admin/hugepages_settings.sh),执行之前对hugepages_settings.sh 这个脚本授可执行的权限[oracle@mydb admin]$ chmod +x hugepages_settings.sh然后,执行hugepages_settings.sh[oracle@mydb admin]$ ./hugepages_settings.sh... ...Press Enter to proceed... Recommended setting: vm.nr_hugepages = 1028计算得到 hugepages 的推荐值为1028 页(注:一页为2M,这个值不可改,1028*2M=2056M),实际上hugepages与参数sga_max_size有关,比sga_max_size的值稍微大一点点(比SGA_MAX_SIZE最少要多加一页,2M的页不要分配超过sga_max_size太多,会造成内存的浪费)3、设置hugepages,在内核参数中添加一行[root@mydb ~]# vi /etc/sysctl.confvm.nr_hugepages = 1028 4、修改内核参数立即生效[root@mydb ~]# sysctl -p5、设定/etc/security/limits.conf文件,以K为单位,必须大于sga_max_size,这里设定为2056000[root@mydb ~]# vi /etc/security/limits.conforacle soft memlock 2056000oracle hard memlock 2056000 6、检查limits是否正确[root@mydb ~]# su - oracle[oracle@mydb ~]$ ulimit -l2056000 7、重启数据库注意:需要在原来的orale用户窗口退到root用户后,重新su - oracle切换到oracle用户,使配置生效。[oracle@mydb ~]$ sqlplus / as sysdbaSQL> shutdown immediate;SQL> startup 8、查看大页的使用情况[oracle@mydb ~]$ watch -n1 'cat /proc/meminfo |grep -i HugePage' Every 1.0s: cat /proc/meminfo |grep -i HugePage Thu Dec 5 11:09:06 2013 HugePages_Total: 1028HugePages_Free: 869HugePages_Rsvd: 842 注:HugePages_Total: 1028 ---总共1028页HugePages_Free: 869 ---空闲548页,即当前大页被使用了1028-869=159页,即被用了159*2M=118M,小于sga_target。HugePages_Rsvd: 842 ---操作系统承诺给Oracle预留842页,即842*2M=1684M(1684+118==SGA_MAX_SIZE)Hugepagesize: 2048 kB --每页是2M,不可修改 使用了hugepage之后,SGA就默认pin在内存里了,那么就不用lock sga了。 9、尝试启用 pre_page_sga 并查看效果注意:参数 pre_page_sga 默认是falseSQL> alter system set pre_page_sga=true scope=spfile; System altered. sys@OCM> show parameter sga NAME TYPE VALUE------------------------------------ ----------- ------------------------------lock_sga boolean FALSEpre_page_sga boolean TRUEsga_max_size big integer 2Gsga_target big integer 1G HugePages_Total: 1028 ---总共1028页HugePages_Free: 548 ---空闲548页,即当前大页被使用了1028-548=480页,即被用了480*2M=960M,约等于sga_target,参数pre_page_sga起作用了。HugePages_Rsvd: 521 ---操作系统承诺给Oracle预留521页,即521*2M=1042M(理解为sga_max_size-sga_target)Hugepagesize: 2048 kB --每页是2M,不可修改
附录:
系统缺省会启用 Transparent HugePages,用来提高内存管理的性能透明大页(Transparent HugePages ), THP 与Hugepages 类似,主要的区别是:Transparent HugePages 可以实时配置,不需要重启才能生效配置。$cat /proc/meminfo | egrep 'Huge|MemTotal|PageTables'MemTotal: 790965276 kBPageTables: 1053188 kBAnonHugePages: 208969728 kBHugePages_Total: 0HugePages_Free: 0HugePages_Rsvd: 0HugePages_Surp: 0Hugepagesize: 2048 kB只要这里 AnonHugePages 的值大于0,即表示启用了THP。在linux 6.2 之后可以通过如下命令来监控THP。$egrep 'trans|thp' /proc/vmstatnr_anon_transparent_hugepages 102079thp_fault_alloc 458782670thp_fault_fallback 25986thp_collapse_alloc 188918thp_collapse_alloc_failed 0thp_split 43215thp_zero_page_alloc 1thp_zero_page_alloc_failed 0查看哪些进程在使用THP:$grep -e AnonHugePages /proc/*/smaps | awk '{ if($2>4) print $0} ' | awk -F "/" '{print $0; system("ps -fp " $3)} ' 因为 THP 会导致节点重启,所以Oracle 强烈建议关闭THP。
