Oracle SHARED POOLRESERVED FREE LIST

发布于:2025-05-28 ⋅ 阅读:(20) ⋅ 点赞:(0)

随着会话不停地从SHARED POOL中分配内存,SHARED POOL中完整连续的内存区域可能会越来越小,这时如果会话需要分配大内存,可能会分配失败。为了减小出现该类型错误的概率,Oracle设置了保留内存区域,该区域用RESERVED FREE LIST管理。其大小由参数SHARED_POOL_RESERVED_SIZE决定(最小为5000字节,最大不能超过SHARED POOL大小的一半)。RESERVED FREE LIST在最高级堆中出现,可以通过DUMP HEAP观察RESERVED FREE LIST:

RESERVED FREE LISTS:
 Reserved bucket 0 size=16
 Reserved bucket 1 size=4400
 Reserved bucket 2 size=8204
 Reserved bucket 3 size=8460
 Reserved bucket 4 size=8464
 Reserved bucket 5 size=8468
 Reserved bucket 6 size=8472
 Reserved bucket 7 size=9296
 Reserved bucket 8 size=9300
 Reserved bucket 9 size=12320
 Reserved bucket 10 size=12324
 Reserved bucket 11 size=16396
 Reserved bucket 12 size=32780
 Reserved bucket 13 size=65548
  Chunk 67000050 sz=   839576  R-free      "               "
  Chunk 68000050 sz=   839576  R-free      "               "
  Chunk 69000050 sz=   839576  R-free      "               "
  Chunk 6b00007c sz=   839532  R-free      "               "
 Reserved bucket 14 size=7968764
Total reserved free space   =  3358260

Oracle对进入RESERVED FREE LIST的对象有大小限制,即只有大于_shared_pool_reserved_min_alloc隐含参数阀值(默认值为4400)的CURSOR才能进入RESERVED FREE LIST。所以有可能出现SHARED POOL有大量空闲空间但进程却无法分配到所需内存的情况,如下所示:

Tue Aug  8 10:52:48 2008
Errors in file /oracle/admin/zhjs/bdump/zhjs2_j000_10084.trc:
ORA-00604: error occurred at recursive SQL level 1
ORA-04031: unable to allocate 4116 bytes of shared memory ("shared pool","JOB$SYS","KGLS heap","KGLS MEM BLOCK"
)

产生这种现象主要有以下2个原因:
SHARED POOL内存碎片化严重,进程无法获得所需大小的内存。即FREE LIST和LRU LIST内存碎片化严重。
所需内存大小没有达到从RESERVED FREE LIST中分配内存的阀值。
通过查询视图V$SHARED_POOL_RESERVED可以观察RESERVED FREE LIST的状态,如下所示:

SQL> select FREE_SPACE,AVG_FREE_SIZE,USED_SPACE,REQUEST_FAILURES,LAST_FAILURE_SIZE
  2  from V$SHARED_POOL_RESERVED;

FREE_SPACE AVG_FREE_SIZE USED_SPACE REQUEST_FAILURES LAST_FAILURE_SIZE
---------- ------------- ---------- ---------------- -----------------
 663913712    155958.119   27944704             2110              4192

可以看到系统共出现过2110次内存分配失败,最近一次分配的内存大小是4192字节,为了减少内存分配失败次数,可以调整_shared_pool_reserved_min_alloc隐含参数至4100字节。需要注意的是,由于存在BUG 3669074,在Oracle 10.2之前查询视图V$SHARED_POOL_RESERVED可能会导致错误结果,可以使用以下脚本观察RESERVED FREE LIST:

select p.inst_id, p.free_space, p.avg_free_size, p.free_count, 
p.max_free_size, p.used_space, p.avg_used_size, p.used_count, p.max_used_size, 
s.requests, s.request_misses, s.last_miss_size, s.max_miss_size, 
s.request_failures, s.last_failure_size, s.aborted_request_threshold, 
s.aborted_requests, s.last_aborted_size 
from (select avg(x$ksmspr.inst_id) inst_id, 
sum(decode(ksmchcls,'R-free',ksmchsiz,0)) free_space, 
avg(decode(ksmchcls,'R-free',ksmchsiz,0)) avg_free_size, 
sum(decode(ksmchcls,'R-free',1,0)) free_count, 
max(decode(ksmchcls,'R-free',ksmchsiz,0)) max_free_size, 
sum(decode(ksmchcls,'R-free',0,ksmchsiz)) used_space, 
avg(decode(ksmchcls,'R-free',0,ksmchsiz)) avg_used_size,   
sum(decode(ksmchcls,'R-free',0,1)) used_count, 
max(decode(ksmchcls,'R-free',0,ksmchsiz)) max_used_size from x$ksmspr 
where ksmchcom not like '%reserved sto%') p, 
  (select sum(kghlurcn) requests, sum(kghlurmi) request_misses, 
  max(kghlurmz) last_miss_size, max(kghlurmx) max_miss_size, 
  sum(kghlunfu) request_failures, max(kghlunfs) last_failure_size, 
  max(kghlumxa) aborted_request_threshold, sum(kghlumer) aborted_requests, 
  max(kghlumes) last_aborted_size from x$kghlu) s;

由于硬解析时需要从SHARED POOL中分配内存(分配内存时需要持有SHARED POOL LATCH),所以在硬解析(HARD PARSE)比较多的系统中,非常容易引起SHARED POOL LATCH的争用。为了减缓该LATCH的争用,从Oracle 9i开始,共享池可分为多个子池来管理(最多7个),下一节将主要讲解SHARED POOL的SUB POOL技术。