主要内容:

1. 介绍

从RedHat6, RedHat7, OL6, OL7 SLES11 and UEK2 kernels开始,透明大页默认是被开启的以便去改善操作系统的内存管理。透明大页与之前版本的传统意义上的HugePages是类似的,最主要的区别在于透明大页

是可以在操作系统运行过程中动态设置的然而传统的hugepages是需要重启操作系统才能生效。

RAC环境下透明大页可能会造成不可预知的节点重启和各种性能问题,另外在单实例的环境下透明大页也会造成不可预知的性能问题。所以oracle强烈建议在所有运行oracle数据库的服务器上关闭透明大页。

2.实验环境:Redhat 6.8 + Oracle 11.2.0.4 RAC

首先检查当前操作系统是否启用透明大页,执行如下两条命令:

1).grep HugePage /proc/meminfo

2).cat /sys/kernel/mm/redhat_transparent_hugepage/enabled

3.确认透明大页是否开启

[[email protected] ~]# grep HugePage /proc/meminfo
AnonHugePages: 264192 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
#若上面的AnonHugePages > 0, 说明启用了透明大页
[[email protected] ~]# cat /sys/kernel/mm/redhat_transparent_hugepage/enabled
[always] madvise never

#若上面扩号是在never的位置,说明禁用了透明大页

官方文档中给出了两种关闭透明大页的方法,但实际测试过程中第二种方法未能关闭透明大页,因此本文只给出一种有效可行的关闭透明大页的方法。如下:

编辑/etc/grub.conf配置文件,在kernel行添加transparent_hugepage=never参数

注:添加transparent_hugepage=never参数时,一定要加到kernel一行中,否则配置不生效。

[[email protected] ~]# vi /etc/grub.conf
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE: You have a /boot partition. This means that
# all kernel and initrd paths are relative to /boot/, eg.
# root (hd0,0)
# kernel /vmlinuz-version ro root=/dev/mapper/vg_rhel6-lv_root
# initrd /initrd-[generic-]version.img
#boot=/dev/sda
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title Red Hat Enterprise Linux 6 (2.6.32-642.el6.x86_64)
root (hd0,0)
kernel /vmlinuz-2.6.32-642.el6.x86_64 ro root=/dev/mapper/vg_rhel6-lv_root transparent_hugepage=never rd_NO_LUKS LANG=en_US.UTF-8 rd_NO_MD SYSFONT=latarcyrheb-sun16
rd_LVM_LV=vg_rhel6/lv_swap crashkernel=auto KEYBOARDTYPE=pc KEYTABLE=us rd_LVM_LV=vg_rhel6/lv_root rd_NO_DM rhgb quiet
initrd /initramfs-2.6.32-642.el6.x86_64.img
~

重启操作系统后查看透明大页是否禁用,如下:

[[email protected] ~]# grep HugePage /proc/meminfo
AnonHugePages: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
[[email protected] ~]# cat /sys/kernel/mm/redhat_transparent_hugepage/enabled
always madvise [never]

4.关闭透明大页

二、开启Linux大页(针对Oracle RAC及Oracle DB服务器)

1. 介绍

(1).减少页表(Page Table)大小。每一个Huge Page,对应的是连续的2MB物理内存,这样12GB的物理内存只需要48KB的Page Table。

(2).Huge Page内存只能锁定在物理内存中,不能被交换到交换区。这样避免了交换引起的性能影响。

(3).由于页表数量的减少,使得CPU中的TLB(可理解为CPU对页表的CACHE)的命中率大大提高。

(4).针对Huge Page的页表,在各进程之间可以共享,也降低了Page Table的大小。

使用大内存页有哪些好处:

2.实验环境:Redhat 6.8 + Oracle 11.2.0.4 RAC

3.1 确操作系统是否支持大页

[[email protected] ~]# grep HugePages /proc/meminfo
AnonHugePages: 0 kB
HugePages_Total: 0
HugePages_Free: 0
HugePages_Rsvd: 0
HugePages_Surp: 0
[[email protected] ~]# grep Hugepagesize /proc/meminfo
Hugepagesize: 2048 kB

HugePages_Total表示系统中配置的大内存页页面数。HugePages_Free表示没有访问过的大内存页面数,这里free容易引起误解,这在稍后有所解释。HugePages_Rsvd表示已经分配但是还未使用的页面

数。Hugepagesize表示大内存页面大小,这里为2MB,注意在有的内核配置中可能为4MB。

HugePages_Free的解释如下:

比如HugePages总计11GB,SGA_MAX_SIZE为10GB,SGA_TARGET为8GB。那么数据库启动后,会根据SGA_MAX_SIZE分配HugePage内存,这里为10GB,真正Free的HugePage内存为11 -10=1G。但是SGA_TARGET只有

8GB,那么会有2GB不会被访问到,则HugePage_Free为2+1=3GB,HugePage_Rsvd内存有2GB。这里实际上可以给其他实例使用的只有1GB,也就是真正意义上的Free只有1GB。

3.2 计划要设置的内存页数量

到目前为止,大内存页只能用于共享内存段等少量类型 的内存。一旦将物理内存用作大内存页,那么这些物理内存就不能用作其他用途,比如作为进程的私有内存。因此不能将过多的内存设置为大内

存页。我们通常将大内存页用作Oracle数据库的SGA,那么大内存页数量:

HugePages_Total=ceil(SGA_MAX_SIZE/Hugepagesize)+N

比如,为数据库设置的SGA_MAX_SIZE为18GB,那么页面数可以为ceil(18*1024/2)+2=9218。这里加上N,是需要将HugePage内存空间设置得比SGA_MAX_SIZE稍大,通常为1 -2即可。我们通过ipcs -m命令查看

共享内存段的大小,可以看到共享内存段的大小实际上比SGA_MAX_SIZE约大。如果服务器上有多个Oracle实例,需要为每个实例考虑共享内存段多出的部分,即N值会越大。另外,Oracle数据库要么全部使

用大内存页,要么完全不使用大内存页,因此不合适的HugePages_Total将造成内存的浪费。

实验环境中:

SQL> show parameter sga

NAME TYPE VALUE

3.开启Linux大页

关闭Linux透明大页和开启大页的方法

2020年5月8日 9:46

分区 Linux 的第 1 页

NAME TYPE VALUE

------------------------------------ ----------- ------------------------------

lock_sga boolean FALSE
pre_page_sga boolean FALSE
sga_max_size big integer 1536M
sga_target big integer 0
HugePages_Total=ceil(1536/2)+2=770

3.3 配置大页数量

修改/etc/sysctl.conf文件配置大页

vm.nr_hugepages=9218

然后执行sysctl –p命令,使配置生效。

这里vm.nr_hugepages这个参数值为第2步计算出的大内存页数量。然后检查/proc/meminfo,如果HugePages_Total小于设置的数量,那么表明没有足够的连续物理内存用于这些大内存页,需要重启服务器。

实验环境中:

[[email protected] ~]# grep vm.nr_hugepages /etc/sysctl.conf
vm.nr_hugepages = 770
[[email protected] ~]# grep HugePages /proc/meminfo
AnonHugePages: 0 kB
HugePages_Total: 626
HugePages_Free: 626
HugePages_Rsvd: 0
HugePages_Surp: 0

表示没有足够的连续物理内存用于这些大页,重启操作系统

[[email protected] ~]# grep HugePages /proc/meminfo
AnonHugePages: 0 kB
HugePages_Total: 770
HugePages_Free: 770
HugePages_Rsvd: 0
HugePages_Surp: 0

3.4 设定oracle用户可以锁定内存的大小

在/etc/security/limits.conf文件中增加如下行:

oracle soft memlock 18878464
oracle hard memlock 18878464

这里设定oracle用户可以锁定内存的大小 ,以KB为单位。

然后重新以oracle用户连接到数据库服务器,使用ulimit -a命令,可以看到:

max lockedmemory (kbytes, -l) 18878464

这里将memlock配置为unlimited也可以。

需要重启操作系统生效

实验环境中:

本次实验环境中SGA=1536M*1024=1572864KB

oracle soft memlock 1572864
oracle hard memlock 1572864
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 15151
max locked memory (kbytes, -l) 1572864
max memory size (kbytes, -m) unlimited
open files (-n) 65536
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 10240
cpu time (seconds, -t) unlimited
max user processes (-u) 16384
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited

3.5 检查Oracle SGA的管理方式

如果数据库使用MANUAL方式管理SGA,需要改为AUTO方式,即将SGA_TARGET_SIZE设置为大于0的值。对于11g,由于HugePage只能用于共享内存,不能用于PGA,所以不能使用AMM,即不能设置MEMORY_TARGET

为大于0,只能分别设置SGA和PGA,SGA同样只能是AUTO方式管理。

实验环境中:

SQL> show parameter pga
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
pga_aggregate_target big integer 10M
SQL> show parameter sga
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
lock_sga boolean FALSE
pre_page_sga boolean FALSE
sga_max_size big integer 1536M
sga_target big integer 1536M
SQL> show parameter memory
NAME TYPE VALUE
------------------------------------ ----------- ------------------------------
hi_shared_memory_address integer 0
memory_max_target big integer 0
memory_target big integer 0
shared_memory_address integer 0
SQL>
[[email protected] ~]# grep HugePages /proc/meminfo
AnonHugePages: 0 kB
HugePages_Total: 770
HugePages_Free: 518
HugePages_Rsvd: 516
HugePages_Surp: 0