- ----------
00000000601072A0 shared pool 24 0 0
0000000060107200 shared pool 24 0 0
0000000060107160 shared pool 24 0 0
00000000601070C0 shared pool 24 0 0
0000000060107020 shared pool 24 0 0
0000000060106F80 shared pool 24 0 0
0000000060106EE0 shared pool 325942 10 1
7 rows selected.
11:02:08 scott@felix SQL>
但是需要注意的是,虽然多缓冲池技术使Oracle可以管理更大的共享池,但是SubPool的划分可能也会导致各分区之间的协调问题,甚至可能因为内存分散而出现ORA-04031错误。最常见的问题是某个子缓冲池(SubPool)可能出现过度使用,当新的进程仍然被分配到这个SubPool时,可能会导致内存请求失败(而此时其他SubPool可能还有很多内存空间)。
select KSMCHIDX "SubPool",
'sgaheap(' || KSMCHIDX || ',0)' sga_heap,
ksmchcom ChunkComment,
decode(round(ksmchsiz / 1000),
0,
'0-1K',
1,
'1-2K',
2,
'2-3K',
3,
'3-4K',
4,
'4-5K',
5,
'5-6k',
6,
'6-7k',
7,
'7-8k',
8,
'8-9k',
9,
'9-10k',
'> 10K') "size",
count(*),
ksmchcls Status,
sum(ksmchsiz) Bytes
fromx$ksmsp
whereKSMCHCOM = 'free memory'
group byksmchidx,
ksmchcls,
'sga heap(' || KSMCHIDX || ',0)',
ksmchcom,
ksmchcls,
decode(round(ksmchsiz / 1000),
0,
'0-1K',
1,
'1-2K',
2,
'2-3K',
3,
'3-4K',
4,
'4-5K',
5,
'5-6k',
6,
'6-7k',
7,
'7-8k',
8,
'8-9k',
9,
'9-10k',
'> 10K');
因为子缓冲池存在的种种问题,从Oracle 10g开始,Oracle允许内存请求在不同SubPool之间进行切换(Switch),从而 高了请求成功的可能(但是显然切换不可能是无限制的,所以问题仍然可能存在)。
8个子池都被使用,其Latch使用情况如下:
select child#, gets
fromv$latch_children
where name= 'shared pool'
order bychild#;
CHILD# GETS
---------- ----------
1 343101
2 24
3 24
4 24
5 24
6 24
7 24
7 rows selected.
11:42:25 sys@felix SQL>
1.2.4 Oracle 10g 共享池管理的增强
子缓冲池的分配的算法很简单:
(1)每个子缓冲池必须满足一定的内存约束;
(2)每4颗CPU可以分配一个子缓冲池,最多7个。
在Oracle 9i中,每个SubPool至少128MB,在Oracle10g中,每个子缓冲池至少为256MB。如前所述,SubPool的数量可以通过_kghdsidx_count参数来控制,但是没有参数可以显示地控制SubPool的大小。
不管Oracle 9i中的128MB以及Oracle10g中的256MB,某些情况下,可能需要增加SubPool的大小。可以通过控制Shared Pool大小以及SubPool的数量来改变SubPool的大小。一些Bug以及内部测试表明500MB的SubPool可能会带来更好的性能,所以从Oracle 11g开始,每个SubPool至少为512MB。
除大小控制之外,在Oracle 10g中,Oracle仍然对共享池的管理做出了进一步改进,那就是对单个子缓冲池进行进一步的细分。现在缺省地,Oracle 10g会将单个缓冲池分割为会4个子分区进行管理(这可能是因为通常4颗CPU才分配一个SubPool),使用类似如上的方法在Oracle 10gR2中进行测试:
分析得到的日志,当仅有一个子缓冲时,SharedPool被划分为sga heap(1,0)~sgaheap(1,3)共4个子分区:
[root@felix~]# cat /u01/app/oracle/diag/rdbms/felix/felix/trace/felix_ora_4324.trc | grep"sga heap"
HEAP DUMP heap name="sga heap" desc=0x60001190
HEAP DUMP heap name="sga heap(1,0)" desc=0x60053f70
HEAP DUMP heap name="sga heap(1,1)" desc=0x600557c8
HEAP DUMP heap name="sga heap(1,2)" desc=0x60057020
HEAP DUMP heap name="sga heap(1,3)" desc=0x60058878
[root@felix ~]#
当使用两个子缓冲时,Shared Pool则被划分为8个子分区进行管理;
Oracle 10g中多缓冲池结构示意图如下图所示
通过一个内部表X$KGHLU([K]ernel [G]eneric memory [H]eap manager State of [L]R[U] OfUnpinned Recreatable chunks)可以查询这些子缓冲池的分配:
11:59:29 sys@felix SQL>selectaddr,indx,kghluidx,kghludur,kghluops,kghlurcr from x$kghlu;
ADDR INDX KGHLUIDX KGHLUDUR KGHLUOPS KGHLURCR
---------------- ---------- ---------- -------------------- ----------
00007FA372851098 0 1 0 119290 4425
12:03:45 sys@felix SQL>
通过这一系列的算法改进,Oracle中Shared Pool管理得以不断增强,较好的解决了大Shared Pool的性能问题;Oracle 8i中,过大Shared Pool设置可能带来的栓锁争用等性能问题在某种程度上得以解决。从Oracle10g开始,Oracle开始 供自动共享内存管理,使用该特性,用户可以不必显示设置共享内存参数,Oracle会自动进行分配和调整,虽然Oracle给我们提供了极大的便利,但是了解自动化后面的原理对于理解Oracle的运行机制仍然是十分重要的。