共享池的改进与ORA-04031的变化
我们知道,从Oracle 9i开始,Shared Pool可以被分割为多个子缓冲池(SubPool)进行管理,以提高并发性,减少竞争。
Shared Pool的每个SubPool可以被看作是一个Mini Shared Pool,拥有自己独立的Free List、内存结构以及LRU List。同时Oracle提供多个Latch对各个子缓冲池进行管理,从而避免单个Latch的竞争(Shared Pool Reserved Area同样进行分割管理)。SubPool最多可以有7个,Shared Pool Latch也从原来的一个增加到现在的7个。如果系统有4个或4个以上的CPU,并且SHARED_POOL_SIZE大于250MB,Oracle可以 把Shared Pool分割为多个子缓冲池(SubPool)进行管理,在Oracle 9i中,每个SubPool至少为128MB。
如果你看到过类似如下信息,那就意味着你可能遇到了SubPool的问题,如下所示:
- Tue Dec 11 17:14:49 2007
- Errors in file
- /oracle/app/admin/ctais2/udump/ctais2_ora_778732.trc:
- ORA-04031: unable to allocate 4216 bytes of shared memory
- ("shared pool","IDX_DJ_NSRXX_P_NSRMCCTAIS2","sga
- heap(2,0)","library cache")
- ORA-04031: unable to allocate 4216 bytes of shared memory
- ("shared pool","IDX_DJ_NSRXX_P_NSRMCCTAIS2","sga
- heap(2,0)","library cache")
- Tue Dec 11 17:14:51 2007
- Errors in file
- /oracle/app/admin/ctais2/bdump/ctais2_pmon_393248.trc:
- ORA-04031: unable to allocate 4216 bytes of shared memory
- ("shared pool","unknown object","sga heap(2,0)","library
- cache")
![]() |
- alter session set events 'immediate trace name
- heapdump level 2';
- alter system set "_kghdsidx_count"=2 scope=spfile;
- startup force;
- alter session set events 'immediate trace name
- heapdump level 2';
以下是概要输出,注意在前者的跟踪文件中,sga heap(1,0)指共享池只存在一个子缓冲,后者则存在sga heap(1,0)以及sga heap(2,0)两个子缓冲池:
- [oracle@jumper udump]$ grep "sga heap" eygle_ora_25766.trc
- HEAP DUMP heap name="sga heap" desc=0x5000002c
- HEAP DUMP heap name="sga heap(1,0)" desc=0x5001ef0c
- [oracle@jumper udump]$ grep "sga heap" eygle_ora_25786.trc
- HEAP DUMP heap name="sga heap" desc=0x5000002c
- HEAP DUMP heap name="sga heap(1,0)" desc=0x5001ef0c
- HEAP DUMP heap name="sga heap(2,0)" desc=0x50023c04
子缓冲池分配的算法很简单:
每个子缓冲池必须满足一定的内存约束条件;
每4颗CPU可以分配一个子缓冲池,子缓冲池的数量最多7个。
在Oracle 9i中,每个SubPool容量至少128MB,而在Oracle 10g中,每个子缓冲池容量至少为256MB。如前所述,SubPool的数量可以通过_KGHDSIDX_COUNT参数来控制,但是没有参数可以显式地控制SubPool的大小。
根据以上规则,在一个12颗CPU的系统中,如果分配容量300MB的Shared Pool,Oracle 9i将创建2个SubPool,每个容量大约150MB,如果共享池容量增加到500MB,Oracle将创建3个SubPool,每个容量大约166MB。
不管是Oracle 9i中的128MB,还是Oracle10g中的256MB,这样的SubPool在许多复杂的系统中,都可能是过小的,在这些情况下,可能要增大 SubPool。可以通过控制Shared Pool大小以及SubPool的数量来改变SubPool的大小。一些Bug以及内部测试表明500MB的SubPool可能会带来更好的性能,所以从 Oracle 11g开始,每个SubPool至少为512MB。
除大小控制之外,在Oracle 10g中,Oracle仍然对共享池的管理做出了进一步改进,那就是对单个子缓冲池进行进一步的细分。现在默认Oracle 10g会将单个缓冲池分割为4个子分区进行管理(这可能是因为通常4颗CPU才分配一个SubPool),使用类似如上的方法在Oracle 10gR2中进行测试:
- alter session set events 'immediate trace name heapdump level 2';
- alter system set "_kghdsidx_count"=2 scope=spfile;
- startup force;
- alter session set events 'immediate trace name heapdump level 2';
分析得到的日志,当仅有一个子缓冲池时,Shared Pool被划分为sga heap(1,0)~sga heap(1,3),共4个子分区:
- [oracle@eygle udump]$ grep "sga heap" eygle_ora_13577.trc
- HEAP DUMP heap name="sga heap" desc=0x2000002c
- HEAP DUMP heap name="sga heap(1,0)" desc=0x2001b550
- HEAP DUMP heap name="sga heap(1,1)" desc=0x2001c188
- HEAP DUMP heap name="sga heap(1,2)" desc=0x2001cdc0
- HEAP DUMP heap name="sga heap(1,3)" desc=0x2001d9f8
当使用两个子缓冲池时,Shared Pool则被划分为8个子分区进行管理:
- [oracle@eygle udump]$ grep "sga heap" eygle_ora_13618.trc
- HEAP DUMP heap name="sga heap" desc=0x2000002c
- HEAP DUMP heap name="sga heap(1,0)" desc=0x2001b550
- HEAP DUMP heap name="sga heap(1,1)" desc=0x2001c188
- HEAP DUMP heap name="sga heap(1,2)" desc=0x2001cdc0
- HEAP DUMP heap name="sga heap(1,3)" desc=0x2001d9f8
- HEAP DUMP heap name="sga heap(2,0)" desc=0x20020640
- HEAP DUMP heap name="sga heap(2,1)" desc=0x20021278
- HEAP DUMP heap name="sga heap(2,2)" desc=0x20021eb0
- HEAP DUMP heap name="sga heap(2,3)" desc=0x20022ae8
Oracle 10g中多缓冲池结构如图1-20所示。
![]() |
通过一个内部表X$KGHLU([K]ernel [G]eneric memory [H]eap manager State of [L]R[U] Of Unpinned Recreatable chunks)可以查询这些子缓冲池的分配:
- SQL> select addr,indx,kghluidx,kghludur,kghluops,kghlurcr
- from x$kghlu;
- ADDR INDX KGHLUIDX KGHLUDUR
- KGHLUOPS KGHLURCR
- -------- ---- ---------- ----------
- ---------- ----------
- B5F4C5B4 0 2 3
- 12773 257
- B5F4C1AC 1 2 2
- 43675 1042
- B5F4D9C8 2 2 1
- 18831 1518
- B5F4D5C0 3 2 0
- 0 0
- B5F4D1B8 4 1 3
- 144697 327
- B5F4E9E4 5 1 2 483428
- 1462
- B5F4E5DC 6 1 1 6558
- 982
- B5F4E1D4 7 1 0
- 0 0
- 8 rows selected.
通过这一系列的算法改进,Oracle中Shared Pool管理得以不断增强,较好地解决了大Shared Pool的性能问题;Oracle 8i中,过大Shared Pool设置可能带来的栓锁争用等性能问题在某种程度上得以解决。从Oracle 10g开始,Oracle开始提供自动共享内存管理,使用该特性,用户可以不必显示设置共享内存参数,Oracle会自动进行分配和调整,虽然 Oracle为用户提供了极大的便利,但是了解自动化后面的原理对于理解Oracle的运行机制仍然是十分重要的。
虽然多缓冲池技术使Oracle可以管理更大的共享池,但是SubPool的划分可能也会导致各分区之间的协调问题,甚至可能因为内存分散而出现 ORA-04031错误。最常见的问题是某个子缓冲池(SubPool)可能出现过度使用,当新的进程仍然被分配到这个SubPool时,可能会导致内存 请求失败(而此时其他SubPool可能还有很多内存空间)。
因为子缓冲池存在的种种问题,从Oracle 10g开始,允许内存请求在不同SubPool之间进行切换(Switch),从而提高了请求成功的可能(但是显然切换不可能是无限制的,所以问题仍然可能存在)。
以下是来自客户系统的一个实际案例,在一个Oracle9i的系统中,经常出现ORA-04031的错误,客户系统的主要配置如下。
- SQL> select * from v$version where rownum <2;
- BANNER
- ----------------------------------------------------------------
- Oracle9i Enterprise Edition Release 9.2.0.6.0 - 64bit Production
- SQL> show parameter cpu_count
- NAME TYPE VALUE
- ------------------------------------ ----------- --
- cpu_count integer 48
- SQL> select * from v$sga;
- NAME VALUE
- ------------------------------ ----------------
- Fixed Size 762240
- Variable Size 2600468480
- Database Buffers 18975031296
- Redo Buffers 6578176
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/16856446/viewspace-628523/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/16856446/viewspace-628523/