占用的总大小是 240+4+4+44 = 296MB,接近于目标的 300MB。注意如图 2 所示,当 SGA_TARGET 改变时,如何自动重新分配池。

图 2:在将 SGA 大小减少到 300MB 之后重新分配池
这些池的大小是动态的。池将根据工作负载扩展,以容纳需求的增长,或缩小以容纳另一个池的扩展。这种扩展或缩小自动发生,无需 DBA 的干预,这与本文开头的示例不同。让我们暂时返回到那个场景,假定在初始分配后,RMAN 作业启动,指示需要一个更大的大型池,大型池将从 4MB 扩展到 40MB,以容纳需求。这个额外的 36MB 将从数据库缓冲中划出,数据库块缓冲将缩小,如图 3 所示。

图 3:在对大型池的需求增长之后经过重新分配的池
池的大小变化基于系统上的工作负载,因此不需要为最坏的情况调整池的大小 — 它们将根据需求的增长自动调整。此外,SGA 的总大小始终在由 SGA_TARGET 指定的最大值之内,因此不存在使内存需求的增长比例失调(这将导致分页和交换)的风险。您可以动态地将 SGA_TARGET 增加至绝对最大值,这个绝对最大值是通过调整参数 SGA_MAX_SIZE 指定的。
哪些池不受影响?
SGA 中的一些池不受动态大小调整的影响,但是必须显式指定这些池。其中值得注意的是非标准块大小的缓冲池,以及 KEEP 池或 RECYCLE 池的非默认块大小。如果您的数据库有一个块大小为 8K,而您想要配置 2K、4K、16K 和 32K 块大小的池,那么您必须手动设置它们。它们的大小将保持不变;它们将不会根据负载缩小或扩展。当使用多种大小的缓冲池、KEEP 池和 RECYCLE 池时,您应当考虑这个因素。此外,日志缓冲不受内存调整的影响 — 不管工作负载如何,在参数 log_buffer 中设定的值是不变的。( 在 10g 中,还可以在 SGA 中定义一种新的池:流池 (stream pool),它用参数 streams_pool_size 进行设置。该池也不受自动内存调整的影响。)
这就产生了一个有趣的问题。如果您需要一个非默认块大小的池,而且想自动管理其它的池,那么该怎么办?
如果您指定了这些非自动调整的参数中的任意一个(如 db_2k_cache_size),那么它们的总大小将从 SGA_TARGET 值中减去,以计算自动调整的参数值,以使 SGA 的总大小保持不变。例如,假设值看起来像这样:
sga_target = 500M
db_2k_cache_size = 50M
其余的池参数未设置。50MB 的 2KB 缓冲池为自动调整的池(如默认块大小缓冲池 (db_cache_size)、共享池、Java 池和大型池)保留了 450MB。当以一种方法动态地调整不可自动调整的参数(如 2KB 块大小池)——这种方法将影响到可自动调整部分的大小,可自动调整的部分将重新调整。例如,将 db_2k_cache_size 的值从 50MB 提高到 100MB 只为可自动调整的参数剩余 400MB。因此,如图 4 所示,可调整的池(如共享池、大型池、Java 池和默认缓冲池)自动缩小,以将它们的总大小从 450MB 减少到 400MB。

图 4:配置非自动缓冲参数的效果
但如果您有足够的可用内存,或者上述风险可能不是那么明显,那应该怎么办?如果这样的话,您可以通过不指定参数文件中的参数 SGA_TARGET、通过在文件中将其设为 0,或者通过使用 ALTER SYSTEM 动态地将其修改为 0 来关闭自动大小调整。当 SGA_TARGET 被设为 0 时,池的当前值被自动设为它们的参数。
使用 Enterprise Manager
您还可以使用 Enterprise Manager 10g 来处理这些参数。从数据库主页中单击超链接 "Memory Parameters",这将显示一个类似于图 5 中的屏幕。

图 5:在 Enterprise Manager 中调整自动共享内存管理
注意红圈中的项目:数据库在 Automatic Shared Memory Management 模式下运行,总大小为 564MB — 与在参数 SGA_TARGET 中指定的值相同。您可以在此修改它,然后单击 Apply 按钮接受这些值;可调整的参数将自动调整。
为每个池指定一个最小值
假定您将 SGA_TARGET 设为 600MB,并且各个池已自动分配:
池 |
大小 (MB) |
缓冲池 |
404 |
Java 池 |
4 |
大型池 |
4 |
共享池 |
148 |
看看上述值,您可能推断 4MB 的 Java 池和大型池可能有点不足;这个值在运行时无疑需要增加。因此,您可能想确保这些池至少在最初时具有更高的值,比如说,分别为 8MB 和 16MB。您可以通过在参数文件中显式地指定这些池的值或动态使用 ALTER SYSTEM 来实现这一目的(如下所示)。
alter system set large_pool_size = 16M;
alter system set java_pool_size = 8M;
现在查看这些池,您可以看到:
SQL> select pool, sum(bytes)/1024/1024 Mbytes from v$sgastat group by pool;
POOL MBYTES
------------ ----------
java pool 8
large pool 16
shared pool 148
SQL> select current_size from v$buffer_pool;
CURRENT_SIZE
------------
388
池的重新分配显示如下:
池 |
大小 (MB) |
缓冲池 |
388 |
Java 池 |
8 |
大型池 |
16 |
共享池 |
148 |
注意 Java 池和大型池是如何分别被重新配置为 8MB 和 16MB,并且注意为了使总的 SGA 保持在 600MB 以下,缓冲池已从 404MB 减少为 388MB。当然,这些池仍然由自动共享内存管理控制 — 它们的大小将根据需求缩小或扩展。您显式指定的值为池的大小设定了一个下限;它们将永远不会缩小到低于这个界限。
结论
Oracle SGA 中的各种池的内存需求不是静态的 — 相反,它们根据系统上的需求而变化。Oracle 数据库 10g 中的自动共享内存管理特性通过动态地将资源重新分配到最需要它们的地方同时施加一个指定的最大值以防止分页和交换,使得 DBA 能够更有效地管理系统内存。更有效的内存管理还带来了更少的内存需求,这使得更精简的硬件更加可行。
有关自动共享内存管理特性的更多信息,请参见 Oracle 数据库性能调整指南的第 7 章。