本节书摘来自华章计算机《Oracle高性能自动化运维》一书中的第1章,第1.4节,作者:冷菠 著,更多章节内容可以访问云栖社区“华章计算机”公众号查看。
1.4 Linux内存体系与Oracle内存空间
1.4.1 Linux用户空间与内核空间
一般来说,Linux操作系统把虚拟地址空间划分为用户空间和内核空间。例如x86架构下的32位Linux虚拟地址空间是4GB(0x0000 0000~0xffff ffff),其中大致将前3GB(0x0000 0000~0xbfff ffff)划分为用户空间,后1GB(0xc000 0000~0xffff ffff)划分为内核空间。
用户程序只能在用户模式(用户空间)下执行,而不能访问特权模式(内核空间)的数据,也不能跳转到内核代码执行,这样的设计可以保护内核,最主要的原因是当一个用户进程访问了非法地址,最坏的情况是该进程崩溃,而不会影响到内核和其他进程正常运行。
CPU在产生中断或异常时会自动切换模式,由用户模式切换到特权模式,这时就可以允许跳转到内核代码中执行中断或异常服务程序。事实上,所有内核代码的执行都是从中断或异常服务程序开始的,整个Linux内核就是由各种中断处理和异常处理程序组成的。
Linux下的Oracle内存分配如图1-3、图1-4所示。
Oracle10g中的SGA与PGA在Linux中是独立分配的,但是在11g中,默认情况下SGA内存区域包含了PGA的内存空间。
1.4.2 Linux下的Oracle内存体系结构
我们知道,Oracle主要是由内存结构和物理结构组成的,如图1-5所示。
图1-5 Oracle体系结构
可以看出,Oracle 内存结构存在于操作系统的用户空间,因此我们在部署Oracle前,就必须事先在Linux操作系统层面配置好Oracle内存地址空间,这样才能成功地配置SGA与PGA,从而避免在安装Oracle的时候出现类似“ORA-27102:out of memory”的错误。
1.4.3 Linux下的Oracle内存分配
Oracle内存结构处于Linux操作系统的用户空间,因此需要通过设置Linux操作系统内核参数来对Oracle 内存进行分配。由于Linux延续了SystemV IPC以及后来的POSIX IPC通信标准,因此Linux下的内存分配主要由以下参数决定,如表1-1所示。
SHMALL在很多系统上是用页面数而不是字节数来计算的。对于一般的Linux来说,Page页的大小一般为4096。
参数SHMMAX是Oracle最重要的Linux内核参数之一,该参数以字节为单位限制单个共享内存段的最大值。与此同时,参数SHMALL用于限制共享内存总数(字节或者Page页)。对于Oracle而言,必须保证这个数值足够大,建议值为超过数据库共享内存与其他共享内存的总和。Oracle官方文档对Linux参数限制描述如图1-6所示。
图1-6 Oracle官方Linux内核参数
我们可以通过以下示例来验证Linux下的Oracle(10g)内存分配:
1)查看Oracle SGA与PGA分配情况,如图1-7所示。
2)查看Linux系统共享内存分配情况,如图1-8所示。
可以看到,Linux系统分配了3个共享内存段,每个共享内存段的大小为2GB。
3)查看Linux环境中的sysctl.conf配置,如图1-9所示。
结合前面内容,不难看出:
单个共享内存段最大值为kernel.shmmax=2147483648B=2GB,与图1-10一致;
SGA=3(共享内存段数量)×2GB(单个内存段最大值)=6GB;
PGA=2GB;
Linux共享内存大小=kernel.shmall=2097152×4096/1024/1024/1024=8GB=SGA(6GB)+PGA(2GB)。
上述内容可以概括如图1-10所示。
结合前面内容,我们可以得出以下结论:
参数kernel.shmmax决定了单个共享内存段的最大值为2GB,即在Linux操作系统层面能分配的单个共享内存段的最大值为2GB。如果所需共享内存大于该值,则需要分配多个共享内存段,以最大共享内存段(2GB)为阈值对所需共享内存段进行拆分分配。
参数kernel.shmall(8GB)决定了Linux操作系统能够提供给Oracle共享内存的上限值,SGA与PGA总和不能超过该阈值。
图1-10 Linux下的Oracle内存分配(10g)
当sga_target设置为6GB时,kernel.shmmax(2GB)决定了Linux系统分配的单个共享内存段上限值,因此需要分配3(6GB/2GB)个共享内存段来提供给SGA。Oracle推荐1个Instance使用1个共享内存段,那么当上述3个共享内存段被分配时,将会在共享内存段之间产生内存地址断层(GAP)。所以当数据库进行IPC通信时,可能存在跨共享内存段的内部数据交互,这样会降低共享内存段间的数据交互效率。因此,建议Linux环境中的Oracle使用1个共享内存段,这样可以减少跨内存段的数据交互,从而提升数据库性能。
图1-10是以Oracle 10g为例进行讲解的,有兴趣的读者可以结合图1-4对Oracle11g进行扩展。