作者:dbtan |【转载时请以超链接形式标明文章出处作者信息】


Oracle 9i 子缓冲池的增强:

从Oracle 9i开始,Shared Pool可以被分割为多个子缓冲池(SubPool)进行管理,每个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,Oralce可以把Shared Pool分割为多个子缓冲池(SubPool)进行管理,在Oracle 9i中,每个SubPool至少128MB。 以下查询显示的是为管理SubPool而新增的子Latch:

sys@NEI> col name for a30
sys@NEI> select addr,name,gets,misses,spin_gets from v$latch_children where name='shared pool';

ADDR     NAME                                 GETS     MISSES  SPIN_GETS
-------- ------------------------------ ---------- ---------- ----------
20096270 shared pool                       9323513       5026       4444
200962D4 shared pool                            64          0          0
20096338 shared pool                            64          0          0
2009639C shared pool                            64          0          0
20096400 shared pool                            64          0          0
20096464 shared pool                            64          0          0
200964C8 shared pool                            64          0          0

已选择7行。

子缓冲的数量受一个新引入的隐含参数_KGHDSIDX_COUNT影响。可以手工调整该参数(仅限于试验环境研究用),观察共享池管理的变化:

sys@NEI> alter system set "_kghdsidx_count"=2 scope=spfile;
系统已更改。
sys@NEI> col KSPPINM for a20
sys@NEI> col KSPPSTVL for a20
sys@NEI> select a.ksppinm,b.ksppstvl from x$ksppi a,x$ksppsv b where a.indx=b.indx and a.ksppinm='_kghdsidx_count';
KSPPINM              KSPPSTVL
-------------------- --------------------
_kghdsidx_count      2

sys@NEI> col name for a20
sys@NEI> select addr,name,gets,misses,spin_gets from v$latch_children where name='shared pool';

ADDR     NAME                       GETS     MISSES  SPIN_GETS
-------- -------------------- ---------- ---------- ----------
20096270 shared pool               31947         13         13
200962D4 shared pool               25951         16         16
20096338 shared pool                   8          0          0
2009639C shared pool                   8          0          0
20096400 shared pool                   8          0          0
20096464 shared pool                   8          0          0
200964C8 shared pool                   8          0          0

已选择7行。

通过如下步骤转储缺省情况以及修改后的Shared Pool,再进行观察:

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可以管理更大的共享池,但是SubPool的划分可能也会导致各分区之间的协调问题,甚至可能因为内存分散而出现 ORA-04031 错误。最常见的问题是某个子缓冲池(SubPool)可能出现过度使用,当新的进程仍然被分配到这个SubPool时,可能会导致内存请求失败(而此时其他SubPool可能还有很多内存空间)。在具体诊断中可以通过如下SQL查询数据库各缓冲池的自由内存空间数量(10g摘要信息):

sys@NEI> select KSMCHIDX "SubPool",'sga heap('||KSMCHIDX||',0)' sga_heap,ksmchcom ChunkComment,
  2  decode(round(ksmchsiz/1000),0,'0-1K',1,'1-2K',2,'2-3K',3,'3-4K',
  3  4,'4-5K',5,'5-6K',6,'6-7K',7,'7-8K',8,'8-9K',9,'9-10K','> 10K') "size",
  4  count(*) ,ksmchcls Status, sum(ksmchsiz) Bytes
  5  from x$ksmsp where KSMCHCOM = 'free memory' group by ksmchidx,ksmchcls,
  6  'sga heap('||KSMCHIDX||',0)',ksmchcom,ksmchcls,decode(round(ksmchsiz/1000),0,'0-1K',
  7  1,'1-2K',2,'2-3K',3,'3-4K',4,'4-5K',5,'5-6K',6,
  8  '6-7K',7,'7-8K',8,'8-9K',9,'9-10K','> 10K')
  9  order by 1;

   SubPool SGA_HEAP           CHUNKCOMMENT     size    COUNT(*) STATUS        BYTES
---------- ------------------ ---------------- ----- ---------- -------- ----------
         1 sga heap(1,0)      free memory      8-9K           2 free          16332
         1 sga heap(1,0)      free memory      0-1K         150 free          14076
         1 sga heap(1,0)      free memory      2-3K           1 free           1920
         1 sga heap(1,0)      free memory      1-2K          18 free          16464
         1 sga heap(1,0)      free memory      4-5K          24 free          96336
         1 sga heap(1,0)      free memory      > 10K          7 free        6648696
         1 sga heap(1,0)      free memory      3-4K           6 free          18756
         1 sga heap(1,0)      free memory      > 10K         10 R-free      2128880
         2 sga heap(2,0)      free memory      > 10K         10 free        4819220
         2 sga heap(2,0)      free memory      1-2K           6 free           5004
         2 sga heap(2,0)      free memory      > 10K         11 R-free      2341768
         2 sga heap(2,0)      free memory      2-3K           1 free           2032
         2 sga heap(2,0)      free memory      4-5K          12 free          46936
         2 sga heap(2,0)      free memory      0-1K          85 free           8284

14 rows selected.

因为子缓冲池存在的种种问题,从Oracle 10g开始,Oracle允许内存请求在不同SubPool之间进行切换(Switch),从而提高了请求成功的可能(但是显然切换不可能是无限制的,所以问题仍然可能存在)。

- The End -