ITPub博客

首页 > Linux操作系统 > Linux操作系统 > 内存结构

内存结构

原创 Linux操作系统 作者:spritesong 时间:2009-05-05 09:44:01 0 删除 编辑

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 KBSORT_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也是一个内存堆,其中定义不同会话特有的结构。如果使用专用服务器来连接OracleUGA 会从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%的空间作为流内存。

“空”池(“Nullpool):这个池其实没有名字。这是块缓冲区(缓存的数据库块)、重做

日志缓冲区和“固定SGA”区专用的内存。

 

SGA 整体大小影响最大的参数如下:

JAVA_POOL_SIZE:控制Java 池的大小。

SHARED_POOL_SIZE:在某种程度上控制共享池的大小。

LARGE_POOL_SIZE:控制大池的大小。

DB_*_CACHE_SIZE:共有8 CACHE_SIZE 参数,控制各个可用的缓冲区缓存的大小。

LOG_BUFFER:在某种程度上控制重做缓冲区的大小。

SGA_TARGETOracle 10g 及以上版本中用于自动SGA 内存管理。

SGA_MAX_SIZE:用于控制数据库启动并运行时SGA 可以达到的最大大小。

自动SGA 内存管

Oracle 10g 开始,又有了一个新的选择:自动SGA 内存管理。如果采用自动SGA 内存管理,数据库实例会根据工作负载条件在运行时分配和撤销(释放)各个SGA 组件。在Oracle 10g 中使用自动SGA 内存管理时,只需把SGA_TARGET 参数设置为所需的SGA 大小,其他与SGA 相关的参数都不用管。

 

不论是使用自动内存管理还是手动内存管理,各个池的内存以一种称为颗粒(granule,也称区组)的单位来分配。一个颗粒是大小为4 MB8 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_SIZEDB_RECYCLE_CACHE_SIZE 等),

并使用计算得到的内存量来设置默认缓冲区池、共享池、大池和Java 池的大小。在运行时,实例会根据需要动态地对这4 个内存区分配和撤销内存。如果共享池内存用光了,实例不会向用户返回一个ORA-04031Unable 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博客 ” ,链接:http://blog.itpub.net/293106/viewspace-592592/,如需转载,请注明出处,否则将追究法律责任。

上一篇: Oracle进程
请登录后发表评论 登录
全部评论

注册时间:2009-03-28

  • 博文量
    62
  • 访问量
    24284