Linux Oracle swap、HugePages、ASMM、内核参数优化

一、swap

经常看到swap分区被使用,被缓存的内容本来是为了增加命中率,结果去不断换入换出,导致本地磁盘IO增加,影响访问速度。所以在内存充足的情况下,如果我们觉得不需要使用swap分区的时候,那就要想办法尽量避免使用swap。下面两种方式可以解决这个问题。

1、swappiness参数

简单地说这个参数定义了系统对swap的使用倾向,默认值为60,值越大表示越倾向于使用swap。可以设为0,这样做并不会禁止对swap的使用,只是最大限度地降低了使用swap的可能性。
查看当前参数:
cat /proc/sys/vm/swappiness
临时性修改:
sysctl vm.swappiness=0
永久修改:
vi /etc/sysctl.conf
vm.swappiness=0
#保存退出后执行下面代码生效
sysctl -p
关闭swap分区:
swapoff -a
free -h

2、hugepage功能

使用hugepages之后可以避免SGA被swap。
直接使用hugepages技术就可以,不要使用lock_sga和pre_page_sga参数,具体原因如下:
1). 根据文档 note 957525.1 和文档 note 1276966.1,启动PRE_PAGE_SGA会引发如下问题:
a) 初始连接到数据库变慢
b) RAC node频繁crash,如果没有使用hugepage
2). 而根据文档 note 1274096.1,再使用hugepages之后就不需要再起用lock_sga参数

二、HugePages

1)目录表,用来存放页表的位置,共1024个目录,每个目录指向一个页表位置。
2)页表,用来存放物理地址页的起始地址,每个页表可以指向1024个物理内存的起始地址。
3)每个内存页4k的物理大小,也就是每个页表指向的是4K的物理内存页。因此页表一共可以指向的物理内存大小为:1024(页表数)*1024(每个页表指向的地址个数)*4K(一个地址4k的物理空间)=4G

为什么使用大页?什么时候使用大页?

而在Redhat Linux中,内存都是以页的形式划分的,默认情况下每页是4K,这就意味着如果物理内存很大,则映射表的条目将会非常多,会影响CPU的检索效率。因为内存大小是固定的,为了减少映射表的条目,可采取的办法只有增加页的尺寸。这种增大的内存页尺寸在Linux 2.1中,称为Big page;在AS 3/4中,称为Hugepage
在Linux中配置hugepage可以提高oracle的性能,减少oracle sga的页交换,类似于aix中的lagepage。

如果Oracle 是11g以后的版本,那么默认创建的实例会使用Automatic Memory Management (AMM)的特性,该特性与HugePage不兼容。
 在设置HugePage之前需要先禁用AMM。设置初始化参数memory_target和memory_max_target为0即可。hugepages 是操作系统的参数, 和amm 没有关系, amm 是数据库内存的, 不管是10g还是11g如果内存大,一定要设置hugepage, 那么就要禁用AMM,设置hugepage后,就要禁用AMM一般超过32G,都需要设置hugepages。

在oracle9i引入了参数pga_aggregate_target对pga进行调整,需要将workarea_size_policy设置为auto才可开启。
在oracle10g中又引入了一个新的参数sga_target来对sga进行自动调整。
ASMM(Automatic Shared Memory Management):实现了oracle sga和pga内部结构的自调节。只有当sga_target为非零时才是ASMM,而只有lock_sga=false时ASMM才可用。对应的内存共享段是真实的共享段。
AMM(Automatic Memory Management):实现了参数memory_target,将sga和pga的规划全部统筹起来对待。对应的内存共享段是“虚拟”共享段(swap)。
默认情况下,Oracle 11g是使用AMM的。我们在安装过程中,指定Oracle使用内存的百分比,这个取值就作为memory_target和memory_max_target的初始取值使用。只有当memory_target为非零时才是AMM,而只有lock_sga=false时AMM才可用。
同时memory_target和memory_max_target这两个参数为0,则AMM自动关闭。
对应的sga_target、pga_aggregate_target参数取值非零之后,Oracle自动使用ASMM特性。

ORACLE  9i       PGA自动管理,SGA手动管理
ORACLE 10g      PGA自动管理,SGA自动管理(ASMM,自动共享内存管理)
ORACLE 11g      PGA,SGA统一自动管理(AMM,自动内存管理)

AMM、ASMM以及手动管理SGA的几种情况的区别,注意这几种方式PGA都是自动管理的。

查看AMM是否开启

sqlplus / as sysdba
SQL> show parameter target;
NAME                                TYPE       VALUE
------------------------------------ ----------- ------------------------------
memory_max_target                   big integer 0
memory_target                       big integer 0

当前memory_target设置为零,AMM没有启用。memory_target为非零,表明此时数据库已经启用AMM。

在进行参数修改之前,可以使用create pfile进行一下参数备份。
参数备份
SQL> show parameter spfile;
SQL> create pfile='spfile_bak' from spfile;
还原备份
SQL> create spfile from pfile='spfile_bak';

关闭AMM

sqlplus / as sysdba
SQL> alter system set memory_max_target=0 scope=spfile;
SQL> alter system set memory_target=0 scope=spfile;

PGA:ProcessGlobal Area是为每个连接到Oracle的用户进程保留的内存。主要包含排序区、会话区、堆栈区和游标区四个部分的内容,他们各司其职,完成用户进程与数据库之间的会话。通常情况下,系统管理员主要关注的是排序区,在必要时需要手工调整这个排序区的大小。
SGA:SystemGlobal Area是OracleInstance的基本组成部分,在实例启动时分配;系统全局域SGA主要由三部分构成:共享池、数据缓冲区、日志缓冲区。共享池:用来存储最近执行的SQL语句和最近使用的数据字典的数据。数据缓冲区:用来存储最近从数据文件中读写过的数据。日志缓冲区:用来记录服务或后台进程对数据库的操作。SGA与操作系统、内存大小、cpu、同时登录的用户数有关。可占系统物理内存的1/3到1/2。

oracle11g的sga和pga设置为多大最合适?

oracle官方文档推荐:
free -m 
总物理内存的20%分配给操作系统和其它应用程序,总物理内存的80%分配给Oracle。

对于oltp(联机事务处理)系统:
sga_target=(物理内存 x 80%) x 80%
sga_max_size=(物理内存 x 80%) x 80%
pga_aggregate_target=(物理内存 x 80%) x 20%

对于dss(数据集)系统,由于会运行一些很大的查询,PGA内存最多分配70%的内存:
sga_target=(物理内存 x 80%) x 50%
sga_max_size=(物理内存 x 80%) x 50%
pga_aggregate_target=(物理内存 x 80%) x 50%
SGA大小调整,需要重启生效
SQL> alter system set sga_target=730m scope=spfile;
SQL> alter system set sga_max_size=730m scope=spfile;
PGA大小调整,不需要重启
SQL> alter system set pga_aggregate_target=200m scope=spfile;
查询spfile文件路径
SQL> show parameter spfile;
/oracle/db/11g/dbs/spfileorcl.ora
关闭数据库
SQL> shutdown immediate;
打开数据库
SQL> startup;

注意,此时如果重新启动系统,会报错。参考https://blog.csdn.net/haiross/article/details/41544821
ora-00843: parameter not taking memory_max_target into account
ora-00849: sga_target 767557632 cannot be set to more than memory_max_target 0.
这个问题的原因是oracle启动过程中对于参数的内部检查。因为memory_max_target被“显示”的赋值,与sga_target赋值相冲突。

解决的方法就是使用参数默认值。创建出pfile之后,将显示赋值为0的memory_target和memory_max_target记录行删除掉。再利用pfile启动数据库,重建spfile。

SQL> create pfile='new_pfile' from spfile;
通过上面show parameter spfile查询到新建配置文件路径为/oracle/db/11g/dbs/new_spfile
vi /oracle/db/11g/dbs/new_pfile
删除下面2行
*.memory_max_target=0
*.memory_target=0
SQL> startup pfile=/oracle/db/11g/dbs/new_pfile;

SQL> create spfile from pfile='new_pfile';
SQL> startup;
ORA-27102: out of memory
Linux-x86_64 Error: 28: No space left on device
Additional information: -536870912
Additional information: 1

该错误是因为Linux 内核参数kernel.shmmax小于sga导致。需要优化内核参数kernel.shmmax。
shmmax 是核心参数中最重要的参数之一,用于定义单个共享内存段的最大值,shmmax 设置应该足够大,能在一个共享内存段下容纳下整个的SGA ,设置的过低可能会导致需要创建多个共享内存段,这样可能导致系统性能的下降 。
kernel.shmmax 可取的最大值为物理内存值 -1byte ,建议值为多于物理内存的一半,一般取值大于 SGA_MAX_SIZE 即可,可以取物理内存 -1byte 。
kernel.shmall :该参数控制可以使用的共享内存的总页数。 Linux 共享内存页大小为 4KB, 共享内存段的大小都是共享内存页大小的整数倍
参考:https://blog.csdn.net/shmily_lsl/article/details/103384366
free -b
kernel.shmmax = total-1
free -k
kernel.shmall=total/4k

修改内核参数 vi /etc/sysctl.conf
kernel.shmmax = 137438953471
kernel.shmall= 33554432
立即生效
sysctl -p

SQL>  startup;
查看数据库内存参数
SQL> show parameter target;
memory_max_target                   big integer 0
memory_target                       big integer 0
pga_aggregate_target                big integer 200M
sga_target                          big integer 730M

SQL> show parameter sga;
SQL> show parameter pga;

设置大页步骤

1、关闭oracle AMM,即把两个参数memory_target 和 memory_max_target设为0。详细参考上面的配置。
2、参考metalink(文档 ID 401749.1)提供的脚本,计算hugepages的大小
vi hugepages_settings.sh

#!/bin/bash
#
# hugepages_settings.sh
#
# Linux bash script to compute values for the
# recommended HugePages/HugeTLB configuration
# on Oracle Linux
#
# Note: This script does calculation for all shared memory
# segments available when the script is run, no matter it
# is an Oracle RDBMS shared memory segment or not.
#
# This script is provided by Doc ID 401749.1 from My Oracle Support
# http://support.oracle.com

# Welcome text
echo "
This script is provided by Doc ID 401749.1 from My Oracle Support
(http://support.oracle.com) where it is intended to compute values for
the recommended HugePages/HugeTLB configuration for the current shared
memory segments on Oracle Linux. Before proceeding with the execution please note following:
 * For ASM instance, it needs to configure ASMM instead of AMM.
 * The 'pga_aggregate_target' is outside the SGA and
   you should accommodate this while calculating the overall size.
 * In case you changes the DB SGA size,
   as the new SGA will not fit in the previous HugePages configuration,
   it had better disable the whole HugePages,
   start the DB with new SGA size and run the script again.
And make sure that:
 * Oracle Database instance(s) are up and running
 * Oracle Database 11g Automatic Memory Management (AMM) is not setup
   (See Doc ID 749851.1)
 * The shared memory segments can be listed by command:
     # ipcs -m
Press Enter to proceed..."

read

# Check for the kernel version
KERN=`uname -r | awk -F. '{ printf("%d.%d\n",$1,$2); }'`

# Find out the HugePage size
HPG_SZ=`grep Hugepagesize /proc/meminfo | awk '{print $2}'`
if [ -z "$HPG_SZ" ];then
    echo "The hugepages may not be supported in the system where the script is being executed."
    exit 1
fi

# Initialize the counter
NUM_PG=0

# Cumulative number of pages required to handle the running shared memory segments
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

RES_BYTES=`echo "$NUM_PG * $HPG_SZ * 1024" | bc -q`

# An SGA less than 100MB does not make sense
# Bail out if that is the case
if [ $RES_BYTES -lt 100000000 ]; then
    echo "***********"
    echo "** ERROR **"
    echo "***********"
    echo "Sorry! There are not enough total of shared memory segments allocated for
HugePages configuration. HugePages can only be used for shared memory segments
that you can list by command:
    # ipcs -m
of a size that can match an Oracle Database SGA. Please make sure that:
 * Oracle Database instance is up and running
 * Oracle Database 11g Automatic Memory Management (AMM) is not configured"
    exit 1
fi

# Finish with results
case $KERN in
    '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" ;;
    '4.14') echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
    '4.18') echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
    '5.4') echo "Recommended setting: vm.nr_hugepages = $NUM_PG" ;;
    *) echo "Kernel version $KERN is not supported by this script (yet). Exiting." ;;
esac

# End

chmod +x hugepages_settings.sh
安装bc
yum -y install bc
./hugepages_settings.sh 

得出大页的大小为1028页(注:一页为2M,这个值不可改,1028*2M=2056M),实际上hugepages与参数sga_max_size有关,比sga_max_size的值稍微大一点点(比SGA_MAX_SIZE最少要多加一页,2M的页不要分配超过sga_max_size太多,会造成内存的浪费)
注意:使用Hugepage内存是共享内存,它会一直keep在内存中的,不会被交换出去,也就是说使用hurgepage的内存不能被其他的进程使用,所以,一定要合理设置这个值,避免造成浪费。对于只使用Oracle的服务器来说,把Hugepage_pool设置成大于SGA大小才能被Oracle使用。
设置hugepages,在内核参数中添加一行,vi /etc/sysctl.conf
vm.nr_hugepages = 1028
修改内核参数立即生效
sysctl -p

资源限制配置

memlock配置
参考 https://oracle-base.com/articles/linux/configuring-huge-pages-for-oracle-on-linux-64
设置至少为以 KB 为单位的 HugePages 分配(HugePages * Hugepagesize)。在这种情况下,该值为 1028*2048=2105344。
别忘记设定/etc/security/limits.conf文件,以K为单位,必须大于sga_max_size,这里设定为HugePages * 2048
vi /etc/security/limits.conf
oracle          soft    memlock 2105344
oracle          hard    memlock 2105344
soft是一个警告值,而hard则是一个真正意义的阀值,超过就会报错

oracle soft nofile 4096  #任何用户可以打开的最大的文件描述符数量,默认1024,这里的数值会限制tcp连接
oracle hard nofile 65536
oracle soft nproc  2047  #任何用户可以打开的最大进程数
oracle hard nproc  16384
soft是一个警告值,而hard则是一个真正意义的阀值,超过就会报错参考 https://oracle-base.com/articles/11g/oracle-db-11gr2-installation-on-oracle-linux-7

检查limits是否正确
su - oracle
ulimit -l

重启数据库
sqlplus / as sysdba
SQL> shutdown immediate;
SQL> startup;

查看大页,已被使用
grep Huge /proc/meminfo
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了。

查看SGA中各个组件分配的内存大小

select * from v$sgainfo;

NAME                                  BYTES RES
-------------------------------- ---------- ---
Buffer Cache Size                 373293056 Yes
Shared Pool Size                  138412032 Yes
Large Pool Size                     4194304 Yes
Java Pool Size                      4194304 Yes 

猜你喜欢

转载自blog.csdn.net/u014644574/article/details/119112203