二、共享池碎片
共享池内存不足的一个主要原因就是共享池碎片。我们先说解决这个问题的方法,很简单,就是使用如下的命令清空共享池:
alter system flush shared_pool;
这条语句也叫做刷新共享池。这条命令将大部分共享池的空间变为了刚启动数据库时的状态。也就是说它清空了大部分共享池中的数据,并且会将碎片进行合并。这条语句对系统的影响是非常大的,因此,不要轻易的使用。一定要在确定了共享池内存问题是因为碎片引起的时,才可以使用它。那么,如何确定共享池是否碎片过多呢。简单的方法是看V$SHARED_POOL_RESERVED视图中的LAST_FAILURE_SIZE列,或者看报出ORA-04031错误时的提示,“请求N字节的内存失败”。如果这个N是一个很小的值,假设只有80字节,也就是说共享池中空闲的内存块都不超过80字节。Oracle会将连续的内存块合并,即使在连续的内存块合并后,也没有了80字节的内存块。这说明共享池中已经有了碎片。或者,也可能是因为共享池内存不足了。要想进一步的判断,我们可以使用我写的脚本Show_sp.sql,它的编写见本章附录,下面是脚本的输出格式:
SQL> @?/sql/show_sp
KSMCHCOM size COUNT(*) STATUS BYTES
---------------- ----- ---------- -------- ----------
free memory 0-1K 356 free 39116
free memory 1-2K 60 free 53576
free memory 2-3K 7 free 14372
free memory 3-4K 8 free 25384
free memory 4-5K 40 free 158144
free memory 5-6k 1 free 5180
free memory 8-9k 1 free 8296
free memory > 10K 11 free 3382344
free memory > 10K 16 R-free 3406208
这个脚本依次显示了0-1K、1-2K、3-4K等等大小的自由内存块数量。通过这个视图我们可以了解到自由内存块的大小分布。我上面这个结果是数据库刚启动时的状态,我们可以看到大小在10K之上的大内存块还有很多。随着用户的操作,大的内存块被不断的切割、变小,大内存块可能会越来越少,也越来越小。如果出现我4031时,通过使用上面的脚本,观察到大小在2K之上的内存块已经被耗尽了,而0-1K,1-2K的内存块却有很多,这基本上就可以确定是碎片太多了。这时就可以通过刷新共享池来解决问题。
不过,有时的4031错误是非常严重的,严重到无论什么操作都无法执行了,对于这种4031错误,只有重启数据库了。
另外说明一点,保留区是不会有碎片的,因为Oracle对保留区内存管理算法进行了改进,所以保留区内不会有碎片。但保留区并不适合存放过小的对象。