Reservedbucket 2 size=8216
Reservedbucket 3 size=8696
Reservedbucket 4 size=8704
Reservedbucket 5 size=8712
Reservedbucket 6 size=8720
Reservedbucket 7 size=9368
Reservedbucket 8 size=9376
Reservedbucket 9 size=12352
Reservedbucket 10 size=12360
Reservedbucket 11 size=16408
Reservedbucket 12 size=32792
Reservedbucket 13 size=65560
Reservedbucket 14 size=1990644
Chunk 0788db800 sz= 968 freeable "vproblem_bucket"
Chunk 0788dbde8 sz= 872 freeable "vproblem_bucket"
Chunk 0788dc370 sz= 872 freeable "vproblem_bucket"
Reservedbucket 0 size=32
Reservedbucket 1 size=4400
Reservedbucket 2 size=8216
Reservedbucket 3 size=8696
Reservedbucket 4 size=8704
Reservedbucket 5 size=8712
Reservedbucket 6 size=8720
Reservedbucket 7 size=9368
Reservedbucket 8 size=9376
Reservedbucket 9 size=12352
Reservedbucket 10 size=12360
Reservedbucket 11 size=16408
Reservedbucket 12 size=32792
Reservedbucket 13 size=65560
Reservedbucket 14 size=1990644
Reservedbucket 0 size=32
Reservedbucket 1 size=4400
Reservedbucket 2 size=8216
Reservedbucket 3 size=8696
Reservedbucket 4 size=8704
Reservedbucket 5 size=8712
Reservedbucket 6 size=8720
Reservedbucket 7 size=9368
Reservedbucket 8 size=9376
Reservedbucket 9 size=12352
Reservedbucket 10 size=12360
Reservedbucket 11 size=16408
Reservedbucket 12 size=32792
Reservedbucket 13 size=65560
Reservedbucket 14 size=1990644
Reservedbucket 0 size=32
Reservedbucket 1 size=4400
Reservedbucket 2 size=8216
Reservedbucket 3 size=8696
Reservedbucket 4 size=8704
Reservedbucket 5 size=8712
Reservedbucket 6 size=8720
Reservedbucket 7 size=9368
Reservedbucket 8 size=9376
Reservedbucket 9 size=12352
Reservedbucket 10 size=12360
Reservedbucket 11 size=16408
Reservedbucket 12 size=32792
Reservedbucket 13 size=65560
Reservedbucket 14 size=1990644
[oracle@felix ~]$
初始地,数据库启动以后,Shared Pool多数是连续内存块。但是当空间分配使用以后,内存块开始被分割,碎片开始出现,Bucket列表开始变长。
Oracle请求Shared Pool空间时,首先进入相应的Bucket进行查找。如果找不到,则转向下一个非空的Bucket,获取第一个Chunk。分割这个Chunk,剩余部分会进入相应的Bucket,进一步增加碎片
最终的结果是,由于不停分割,每个Bucket上的内存块会越来越多,越来越碎小。通常Bucket 0的问题会最为显著,在这个测试数据库上,Bucket 0上的碎片已经达到9030个,而shared_pool_size设置仅为150MB。
通常如果每个Bucket上的Chunk多于2000个,就被认为是Shared Pool碎片过多。Shared Pool的碎片过多,是Shared Pool产生性能问题的主要原因。
碎片过多会导致搜索Free Lists的时间过长,而我们知道,Free Lists的管理和搜索都需要获得和持有一个非常重要的Latch,就 是Shared Pool Latch。Latch是Oracle数据库内部提供的一种低级锁,通过串行机制保护共享内存不被并发更新/修改所损坏。Latch的持有通常都非常短暂(通常微秒级),但是对于一个繁忙的数据库,这个串行机制往往会成为极大的性能瓶颈。
如果Free Lists链表过长,搜索这个Free Lists的时间就会变长,从而可能导致Shared Pool Latch被长时间持有,在一个繁忙的系统中,这会引起严重的Shared PoolLatch的竞争。在Oracle 9i之前,这个重要的Shared Pool Latch只有一个,所以长时间持有将会导致严重的性能问题。
1.2.3 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,Oracle可以把Shared Pool分割为多个子缓冲池(SubPool)进行管理,在Oracle 9i中,每个SubPool至少为128MB。
Oracle 9i中多个子缓冲池的结构示意如图所示:
以下查询显示的是为管理SubPool而新增的子Latch:
select addr, name, gets, misses, spin_gets
fromv$latch_children
where name = 'shared pool';
ADDR NAME GETS MISSES SPIN_GETS
-------------------------------------------------------- ---------- ---------