4.1 进程全局区和用户全局区
进程全局区(PGA)是特定于进程的一段内存。PGA 绝对不会在Oracle 的SGA 中分配,而总是由进程或线程在本地分配。
如果通过一个共享服务器连接,UGA 肯定存储在每个共享服务器进程都能访问的一个内存结构中,也就是SGA 中。
如果使用一个专用服务器连接,则不再需要大家都能访问你的会话状态,UGA 几乎成了PGA 的同义词;实际上,UGA 就包含在专用服务器的PGA 中。所以,PGA 包含进程内存,还可能包含UGA。
PGA 内存中的其他区通常用于完成内存中的排序、位图,合并以及散列。可以肯定地说,除了UGA 内存,这些区在PGA 中的比重最大。从Oracle9i Release 1 起,有两种办法来管理PGA 中的这些非UGA 内存:
PGA 内存管理受数据库初始化参数WORKAREA_SIZE_POLICY 的控制,而且可以在会话级修改。
4.1.1 手动PGA 内存管理
有些参数对PGA 大小的影响最大,这些参数如下:
SORT_AREA_SIZE:在信息换出到磁盘之前,用于对信息排序的RAM 总量。
SORT_AREA_RETAINED_SIZE:排序完成后用于保存已排序数据的内存总量。也就是说,如果SORT_AREA_SIZE 是512 KB,SORT_AREA_RETAINED_SIZE 是256 KB,那么服务器进程最初处理查询时会用512 KB 的内存对数据排序。等到排序完成时,排序区会“收缩”为256 KB,这256 KB内存中放不下的已排序数据会写出到临时表空间中。
HASH_AREA_SIZE:服务器进程在内存中存储散列表所用的内存量。散列联结时会使用这些散列表结构,通常把一个大集合与另一个集合联结时就会用到这些结构。两个集合中较小的一个会散列到内存中,散列区中放不下的部分都会通过联结键存储在临时表空间中。
4.1.2 自动PGA 内存管理
建立自动PGA 内存管理时,需要为两个实例初始化参数确定适当的值,这两个参数是
WORKAREA_SIZE_POLICY:默认值是AUTO,这也是推荐的设置。
PGA_AGGREGATE_TARGET::这个参数会控制实例为完成数据排序/散列的所有工作区(即排序区和散列区)总共应分配多少内存。
可以在会话中通过ALTER SESSION 命令“打开”自动PGA 内存管理,也可以在系统级通过ALTER SYSTEM 命令[2]打开。
1. 确定如何分配内存
所谓工作区(work area)只是排序区和散列区的另一种通用说法。每个工作区只会用PGA_AGGREGATE_TARGET 中不到5%的内存。
一个并行查询最多可以使用PGA_AGGREGATE_TARGET 的30%,每个并行进程会在这30%中得到自己的那一份。也就是说,每个并行进程能使用的内存量大约是0.3*PGA_ AGGREGATE_TARGET/ (并行进程数)。
要设置
PGA_AGGREGATE_TARGET,也就是你希望Oracle 能自由使用多大的内存来完成排序和散列,从概念上讲这比得出最佳的SORT|HASH_AREA_SIZE 要容易得多,特别是,SORT|HASH_AREA_SIZE 之类的参数并没有一个最佳的值;“最佳值”会随工作负载而变化。
总结:PGA 是进程专用的内存区。这是Oracle专用或共享服务器需要的一组独立于会话的变量。PGA 是一个内存“堆”,其中还可以分配其他结构。UGA也是一个内存堆,其中定义不同会话特有的结构。如果使用专用服务器来连接Oracle,UGA 会从PGA 分配,
如果使用共享服务器连接,UGA 则从SGA 分配。这说明,使用共享服务器时,必须适当地设置SGA 中大池(large pool)的大小,以便有足够的空间来适应可能并发地连接数据库的每一个用户。所以,如果数据库支持共享服务器连接,与有类似配置但只使用专用服务器模式的数据库相比,前者的SGA 通常比后者大得多。
4.2 系统全局区
在Oracle 自身内,则完全可以看到SGA,而不论平台是什么。为此,只需使用另一个神奇的V$视图,名为V$SGASTAT。
SGA 分为不同的池(pool):
Java 池(Java pool): Java 池是为数据库中运行的JVM 分配的一段固定大小的内存。在
Oracle10g 中,Java 池可以在数据库启动并运行时在线调整大小。
大池(Large pool):共享服务器连接使用大池作为会话内存,并行执行特性使用大池作为
消息缓冲区,另外RMAN 备份可能使用大池作为磁盘I/O 缓冲区。在Oracle 10g 和9i Release 2中,大池都可以在线调整大小。
共享池(Shared pool):共享池包含共享游标( cursor)、存储过程、状态对象、字典缓存
和诸如此类的大量其他数据。在Oracle 10g 和9i 中,共享池都可以在线调整大小。
流池(Stream pool):这是Oracle 流(Stream)专用的一个内存池,Oracle 流是数据库中
的一个数据共享工具。这个工具是Oracle 10g 中新增的,可以在线调整大小。如果未配置流池,但是使用了流功能,Oracle 会使用共享池中至多10%的空间作为流内存。
“空”池(“Null”pool):这个池其实没有名字。这是块缓冲区(缓存的数据库块)、重做
日志缓冲区和“固定SGA”区专用的内存。

对SGA 整体大小影响最大的参数如下:
JAVA_POOL_SIZE:控制Java 池的大小。
SHARED_POOL_SIZE:在某种程度上控制共享池的大小。
LARGE_POOL_SIZE:控制大池的大小。
DB_*_CACHE_SIZE:共有8 个CACHE_SIZE 参数,控制各个可用的缓冲区缓存的大小。
LOG_BUFFER:在某种程度上控制重做缓冲区的大小。
SGA_TARGET:Oracle 10g 及以上版本中用于自动SGA 内存管理。
SGA_MAX_SIZE:用于控制数据库启动并运行时SGA 可以达到的最大大小。
自动SGA 内存管
从Oracle 10g 开始,又有了一个新的选择:自动SGA 内存管理。如果采用自动SGA 内存管理,数据库实例会根据工作负载条件在运行时分配和撤销(释放)各个SGA 组件。在Oracle 10g 中使用自动SGA 内存管理时,只需把SGA_TARGET 参数设置为所需的SGA 大小,其他与SGA 相关的参数都不用管。
不论是使用自动内存管理还是手动内存管理,各个池的内存以一种称为颗粒(granule,也称区组)的单位来分配。一个颗粒是大小为4 MB、8 MB 或16 MB 的内存区。通过查询V$SGA_DYNAMIC_ COMPONENTS,可以查看各个池所用的颗粒大小。
4.2.1 固定SGA
4.2.2 重做缓冲区
实际上,LGWR 会在以下某个情况发生时启动对这个区的刷新输出(flush):
1. 每3 秒一次
2. 无论何时有人提交请求
3. 要求LGWR 切换日志文件
4. 重做缓冲区1/3 满,或者包含了1 MB 的缓存重做日志数据
由于这些原因,如果重做缓冲区的大小超过几MB,通常对系统就没有什么意义了
重做缓冲区的默认大小由LOG_BUFFER 参数控制,取值为512 KB 和(128 * CPU 个数)KB 中的较大者。这个区的最小大小取决于操作系统。如果想知道到底是多少,只需将LOG_BUFFER 设置为1 字节,再重启数据库
4.2.3 块缓冲区缓存
Oracle将数据库块写至磁盘之前,另外从磁盘读取数据库块之后,就会把这些数据库块存储在块缓冲区缓存(block buffer cache)中。可以把SGA 中各个段的已缓存块放在3 个位置上(这些池之间没有共享):
默认池(default pool):
保持池(keep pool)
回收池(recycle pool)
下面来看在这些池中如何管理块。
1. 在缓冲区缓存中管理块
缓冲区缓存中的块实质上在一个位置上管理,但有两个不同的列表指向这些块:
脏(dirty)块列表,其中的块需要由数据库块写入器(DBWn;稍后将介绍这个进程)写入
磁盘。
非脏(nondirty)块列表。
我们并不需要关心所有细节,只要知道频繁使用的块会被缓存,不常使用的块不会缓存太久,这就够了。
2. 多个块大小
你可以有一个“默认的”块大小(最初创建数据库时使用的块大小;即SYSTEM 和所有TEMPORARY 表空间的块大小),以及最多4 个其他的块大小。每个不同的块大小都必须有其自己的缓冲区缓存。默认池、保持池和回收池只缓存具有默认大小的块。
为了在数据库中使用非默认的块大小,需要配置一个缓冲区池来保存这些块。
我可以设置DB_16K_CACHE_SIZE 参数,并重启数据库。也可以缩小另外的某个SGA
组件,从而在现有的SGA 中腾出空间来建立一个16 KB 的缓存。或者,如果SGA_MAX_SIZE 参数大于当前的SGA 大小,我还可以直接分配一个16 KB 的缓存。
多个块大小主要用于从一个数据库向另一个数据库传输数据
4.2.4 共享池
共享池就是Oracle 缓存一些“程序”数据的地方. 共享池的特点是有大量小的内存块(chunk),一般为4 KB 或更小。要记住,4 KB 并不是一个硬性限制,可能有的内存分配会超过这个大小,但是一般来讲,我们的目标是使用小块的内存来避免碎片问题。如果分配的内存块大小显著不同(有的很小,有的却相当大),就可能出现碎片问题。共享池中的内存根据LRU(最近最少使用)的原则来管理
关于共享池和参数SHARED_POOL_SIZE 还有一点要说明。在Oracle9i 及以前的版本中,查询的结果与SHARED_POOL_SIZE 参数之间没有直接的关系.
如果实在要谈谈它们的关系,只能说SUM(BYTES) FROM V$SGASTAT 总是大于SHARED_ POOL_SIZE。共享池还保存了另外的许多结构,它们不在相应参数的作用域内。SHARED_POOL_SIZE 通常占了共享池(SUM(BYTES)报告的结果)中最大的一部分,但这不是共享池中惟一的一部分.
不过,在Oracle 10g 及以上版本中,应该能看到二者之间存在一对一的对应关系,假设你使用手动的SGA 内存管理(也就是说,自己设置SHARED_POOL_SIZE 参数):
总结:如果你从Oracle9i 或之前的版本转向10g,这是一个相当重要的改变。在Oracle10g 中,SHARED_POOL_SIZE 参数控制了共享池的大小,而在Oracle9i 及之前的版本中,它只是共享池中贡献最大的部分。
4.2.5 大池
之所以称之为大池,是因为它用于大块内存的分配,共享池不会处理这么大的内存块。
大池专门用于以下情况:
共享服务器连接,用于在SGA 中分配UGA 区
语句的并行执行,允许分配进程间的消息缓冲区,这些缓冲区用于协调并行查询服务器。
备份,在某些情况下用于RMAN 磁盘I/O 缓冲区。
4.2.6 Java池
4.2.7 流池
4.2.8 自动SGA 内存管理
在Oracle9i 及以前版本中,只能用手动SGA 内存管理,不存在参数SGA_TARGET,而且参数SGA_MAX_SIZE 只是一个上限,而不是动态目标。
要使用自动SGA 内存管理,参数STATISTICS_LEVEL 必须设置为TYPICAL 或ALL。如果不支持统计集合,数据库就没有必要的历史信息来确定大小。
采用自动SGA 内存管理时,确定自动调整组件大小的主要参数是SGA_TARGET,这个参数可以在数据
库启动并运行时动态调整,最大可以达到SGA_MAX_SIZE 参数设置的值(默认等于SGA_TARGET,所以如果
想增加SGA_TARGET,就必须在启动数据库实例之前先把SGA_MAX_SIZE 设置得大一些)。数据库会使用
SGA_TARGET 值,再减去其他手动设置组件的大小(如DB_KEEP_CACHE_SIZE、DB_RECYCLE_CACHE_SIZE 等),
并使用计算得到的内存量来设置默认缓冲区池、共享池、大池和Java 池的大小。在运行时,实例会根据需要动态地对这4 个内存区分配和撤销内存。如果共享池内存用光了,实例不会向用户返回一个ORA-04031“Unable to allocate N bytes of shared memory”(无法分配N 字节的共享内存)错误,而是会把缓冲
区缓存缩小几MB(一个颗粒的大小),再相应地增加共享池的大小。
随着时间的推移,当实例的内存需求越来越确定时,各个SGA 组件的大小也越来越固定。即便数据库关闭后又启动,数据库还能记得组件的大小,因此不必每次都从头再来确定实例的正确大小。这是通过4个带双下划线的参数做到的: __DB_CACHE_SIZE 、__JAVA_POOL_SIZE 、__LARGE_POOL_SIZE 和
__SHARED_POOL_SIZE。如果正常或立即关闭数据库,则数据库会把这些值记录到存储参数文件(SPFILE)中,并在启动时再使用这些值来设置各个区的默认大小。
另外,如果知道4 个区中某个区的最小值,那么除了设置SGA_TARGET 外,还可以设置这个参数。实例会使用你的设置作为下界(即这个区可能的最小大小)。
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/293106/viewspace-592592/ ,如需转载,请注明出处,否则将追究法律责任。