4.2 系统全局区
每个Oracle实例都有一个很大的内存结构,称为系统全局区(System Global Area,SGA)。这是一个庞大的共享内存结构,每个Oracle进程都会访问其中的某一点。SGA的大小不一,在小的测试系统上只有几MB,在中到大型系统上可能有几百MB,对于非常大的系统,甚至多达几GB。
在UNIX操作系统上,SGA是一个物理实体,从操作系统命令行上能“看到”它。它物理地实现为一个共享内存段,进程可以附加到这段独立的内存上。系统上也可以只有SGA而没有任何Oracle进程;只有内存而已。不过,需要说明,如果有一个SGA而没有任何Oracle进程,这就说明数据库以某种方式崩溃了。这是一种很罕见的情况,但是确实有可能发生。以下是Red Hat Linux上SGA的“样子”:

这里表示了3个SGA:一个属于操作系统用户ora10g,另一个属于操作系统用户ora9ir2,第3个属于操作系统用户ora9ir1,大小分别约512 MB、112 MB和124 MB。
在Windows上,则无法像UNIX/Linux上那样把SGA看作一个实体。由于在Windows平台上, Oracle会作为有一个地址空间的单个进程来执行,所以SGA将作为专用(私有)内存分配给oracle.exe进程。如果使用Windows Task Manager(任务管理器)或其他性能工具,则可以看到oracle.exe总共分配了多少空间,但是SGA和其他已分配的内存无法看到。
在Oracle自身内,则完全可以看到SGA,而不论平台是什么。为此,只需使用另一个神奇的V$视图,名为V$SGASTAT。它可能如下所示(注意,这个代码并非来自前面的系统;而是来自一个已经适当地配置了相应特性的系统,从而可以查看所有可用的池):
![]()
![]()

SGA分为不同的池(pool):
q Java池(Java pool):Java池是为数据库中运行的JVM分配的一段固定大小的内存。在Oracle10g中,Java池可以在数据库启动并运行时在线调整大小。
q 大池(Large pool):共享服务器连接使用大池作为会话内存,并行执行特性使用大池作为消息缓冲区,另外RMAN备份可能使用大池作为磁盘I/O缓冲区。在Oracle 10g 和 9i Release 2中,大池都可以在线调整大小。
q 共享池(Shared pool):共享池包含共享游标(cursor)、存储过程、状态对象、字典缓存和诸如此类的大量其他数据。在Oracle 10g和9i中,共享池都可以在线调整大小。
q 流池(Stream pool):这是Oracle流(Stream)专用的一个内存池,Oracle流是数据库中的一个数据共享工具。这个工具是Oracle 10g中新增的,可以在线调整大小。如果未配置流池,但是使用了流功能,Oracle会使用共享池中至多10%的空间作为流内存。
q “空”池(“Null”pool):这个池其实没有名字。这是块缓冲区(缓存的数据库块)、重做日志缓冲区和“固定SGA”区专用的内存。
典型的SGA可能如图4-1所示。

图4-1 典型的SGA
对SGA整体大小影响最大的参数如下:
q JAVA_POOL_SIZE:控制Java池的大小。
q SHARED_POOL_SIZE:在某种程度上控制共享池的大小。
q LARGE_POOL_SIZE:控制大池的大小。
q
DB_*_CACHE_SIZE:共有8个CACHE_SIZE参数,控制各个可用的缓冲区缓存的大小。
q LOG_BUFFER:在某种程度上控制重做缓冲区的大小。
q SGA_TARGET:Oracle 10g及以上版本中用于自动SGA内存管理。
q SGA_MAX_SIZE:用于控制数据库启动并运行时SGA可以达到的最大大小。
在Oracle9i中,各个SGA组件必须由DBA手动地设置大小,但是从Oracle 10g开始,又有了一个新的选择:自动SGA内存管理。如果采用自动SGA内存管理,数据库实例会根据工作负载条件在运行时分配和撤销(释放)各个SGA组件。在Oracle 10g中使用自动SGA内存管理时,只需把SGA_TARGET参数设置为所需的SGA大小,其他与SGA相关的参数都不用管。只要设置了SGA_TARGET参数,数据库实例就会接管工作,根据需要为各个池分配内存,随着时间的推移,甚至还会从一个池取出内存交给另一个池。
不论是使用自动内存管理还是手动内存管理,都会发现各个池的内存以一种称为颗粒(granule,也称区组)的单位来分配。一个颗粒是大小为4 MB、8 MB或16 MB的内存区。颗粒是最小的分配单位,所以如果想要一个5 MB的Java池,而且颗粒大小为4 MB,Oracle实际上会为这个Java池分配8 MB(在4的倍数中,8是大于或等于5的最小的数)。颗粒的大小由SGA的大小确定(听上去好像又转回来了,因为SGA的大小取决于颗粒的大小)。通过查询V$SGA_DYNAMIC_ COMPONENTS,可以查看各个池所用的颗粒大小。实际上,还可以使用这个视图来查看SGA的总大小如何影响颗粒的大小:

在这个例子中,我使用了自动SGA内存管理,并通过一个参数(SGA_TARGET)来控制SGA的大小。SGA小于1 GB时,颗粒为4 MB。当SGA大小增加到超过阈值1 GB时(对于不同的操作系统,甚至对于不同的版本,这个阈值可能稍有变化),可以看到颗粒大小有所增加:


可以看到,SGA为1.5 GB时,会以16 MB的颗粒为池分配空间,所以池大小都将是16 MB的某个倍数。
记住这一点,下面逐一分析各个主要的SGA组件。





