第一种错误的原因很明显:分配给共享池的内存不足以满足用户请求。(在某些情况下,原因可能不是池本身的大小,而是未使用绑定变量导致的过多分析造成的碎片,这是我很喜欢的一个主题;但目前让我们把重点放在手头的问题上。)其它的错误分别来自大型池和 java 池的空间不足。 您需要解决这些错误情况,而不作任何与应用程序相关的修改。那么有哪些方案可选呢?问题是如何在 Oracle 例程所需的所有池之间划分可用的内存。 馅饼怎么分? 正如您所了解的,一个 Oracle 例程的系统全局区域 (SGA) 包含几个内存区域(包括缓冲高速缓存、共享池、Java 池、大型池和重做日志缓冲)。这些池在操作系统的内存空间中占据了固定的内存数;它们的大小由 DBA 在初始化参数文件中指定。 这四个池(数据库块缓冲高速缓存、共享池、Java 池和大型池)几乎占据了 SGA 中所有的空间。(与其它区域相比,重做日志缓冲没有占据多少空间,对我们这里的讨论无关紧要。)作为 DBA,您必须确保它们各自的内存分配是充足的。 假定您决定了这些池的值分别是 2GB、1GB、1GB 和 1GB。您将设置以下初始化参数来为数据库例程规定池的大小。| db_cache_size = 2g shared_pool_size = 1g large_pool_size = 1g java_pool_size = 1g |
现在,仔细看一下这些参数。坦白讲,这些值是否准确?我相信您一定会有疑虑。在实际中,没有人能够为这些池指定确切的内存数 — 它们太依靠于数据库内部的处理,而处理的特性随时在变化。 下面是一个示例场景。假定您有一个典型的、大部分属于 OLTP 的数据库,并且为缓冲高速缓存分配的专用内存比为纯 OLTP 数据库(现在已经很少见了)分配的要少。有一天,您的用户放开了一些非常大的全表扫描,以创建当天的结束报表。Oracle9i 数据库为您提供了在线修改内存分配的功能,但由于提供的总物理内存有限,您决定从大型池和 Java 池中取出一些内存:| alter system set db_cache_size = 3g scope=memory; alter system set large_pool_size = 512m scope=memory; alter system set java_pool_size = 512m scope=memory; |
这个解决方案能够很好地工作一段时间,但是接着夜间的 RMAN 作业(它们使用大型池)开始了,大型池将立即出现内存不足。同样,您从数据库高速缓存中取出一些内存来补充大型池,以拯救这种局面。 RMAN 作业完成,然后启动一个广泛使用 Java 的批处理程序,接着您开始看到与 Java 池相关的错误。因此,您(再次)重新分配池,以满足 Java 池和数据库高速缓存上的内存需求:| alter system set db_cache_size = 2G scope=memory; alter system set large_pool_size = 512M scope=memory; alter system set java_pool_size = 1.5G scope=memory; |
第二天早上,OLTP 作业恢复在线,这个循环又完全重复!解决这种恶性循环的一种替代方法是永久设置每个池的最大需求。不过,这么做的话,您分配的总的 SGA 可能超出可用的内存 — 从而在为每个池分配的内存数不足时,将增加交换和分页的风险。人工重新分配的方法(虽然不实际)目前看起来很不错。 另一种替代方法是将值设为可接受的最小值。不过,当需求增长且内存不能完全满足时,性能将受到影响。 注重在所有这些示例中,分配给 SGA 的总内存保持不变,而池之间的内存分配根据即时的需求进行修改。假如 RDBMS 将自动探测来自用户的需求并相应地重新分布内存分配,那不是很好吗? Oracle 数据库 10g 中的自动共享内存治理特性正好能够实现这一目的。您可以决定 SGA 的总大小,然后设置一个名称为 SGA_TARGET 的参数,这个参数决定 SGA 的总大小。SGA 内部的各个池将根据工作负载动态地进行配置。实现自动内存分配仅仅需要 SGA_TARGET 参数的一个非零值。 设置自动共享内存治理 让我们看看该特性是如何工作的。首先,确定 SGA 的总大小。您可以通过确定现在分配了多少内存来估计这个值。| SQL> select sum(value)/1024/1024 from v$sga; SUM(VALUE)/1024/1024 -------------------- 500 |
此时 SGA 的当前总大小近似为 500MB,并且这个值将变为 SGA_TARGET 的值。接下来,执行语句:| alter system set sga_target = 500M scope=both; |
这种方法不需要为各个池设置不同值;因而,您将需要在参数文件中使它们的值为零或全部删除它们。| shared_pool_size = 0 large_pool_size = 0 java_pool_size = 0 db_cache_size = 0 |
再循环数据库,使这些值生效。这个人工过程还可以通过 EnterPRise Manager 10g 实施。从数据库主页中,选择 "Administration" 选项卡,然后选择 "Memory Parameters"。对于人工配置的内存参数,将显示标记为 "Enable" 的按钮,以及所有人工配置的池的值。单击 "Enable" 按钮,启用自动共享内存治理特性。企业治理器将完成剩下的工作。 在配置了自动内存分配之后,您可以利用以下命令检查它们的大小:
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/27202875/viewspace-738533/
,如需转载,请注明出处,否则将追究法律责任。