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


了解X$KSMSP视图:

Shared Pool的空间分配和使用情况,可以通过一个内部视图来观察,这个视图就是X$KSMSP([K]ernal [S]torage [M]emory Management [S]GA Hea[P]),其中每一行都代表着Shared Pool中的一个Chunk。以下是X$KSMSP的结构:

sys@CCDB> desc x$ksmsp
Name                     Null?    Type
------------------------ -------- ----------------
ADDR                              RAW(8)
INDX                              NUMBER
INST_ID                           NUMBER
KSMCHIDX                          NUMBER
KSMCHDUR                          NUMBER
KSMCHCOM                          VARCHAR2(16)
KSMCHPTR                          RAW(8)
KSMCHSIZ                          NUMBER
KSMCHCLS                          VARCHAR2(8)
KSMCHTYP                          NUMBER
KSMCHPAR                          RAW(8)

这里需要关注一下以下几个字段。

⑴ x$ksmsp.ksmchcom 是注释字段,每个内存块被分配以后,注释会添加在该字段中。
⑵ x$ksmsp.ksmchsiz 代表块大小。
⑶ x$ksmsp.ksmchcls 列代表类型,主要有4类,具体说明如下:
·free:即Free Chunks,不包含任何对象的Chunk,可以不受限制的被自由分配。
·recr:即Recreatable Chunks,包含可以被临时移出内存的对象,在需要的时候,这个对象可以被重新创建。例如,许多存储共享SQL代码的内存都是可以重建的。
·freeable:即Freeable Chunks,包含session周期或调用的对象,随后可以被释放。这部分内存有时候可以全部或部分提前释放。但是注意,由于某些对象是中间过程产生的,这些对象不能临时被移出内存(因为不可重建)。
·perm:即Permanent Memory Chunks,包含永久对象,通常不能独立释放。

从以上引用的trace文件中,摘出开头一段,可以清楚地看到Oracle对这部分Chunk的记录情况:

HEAP DUMP heap name="sga heap(1,0)"  desc=0x2001aae4
extent sz=0xfc4 alt=108 het=32767 rec=9 flg=-126 opc=0
parent=(nil) owner=(nil) nex=(nil) xsz=0x400000
EXTENT 0 addr=0x41000000
  Chunk 41000038 sz=       24  R-freeable  "reserved stoppe"
  Chunk 41000050 sz=   212888  R-free      "               "
  Chunk 41033fe8 sz=       24  R-freeable  "reserved stoppe"
  Chunk 41034000 sz=  3981312    perm      "perm           "  alo=3955992
EXTENT 1 addr=0x41400000
  Chunk 41400038 sz=       24  R-freeable  "reserved stoppe"
  Chunk 41400050 sz=   212888  R-free      "               "
  Chunk 41433fe8 sz=       24  R-freeable  "reserved stoppe"
  Chunk 41434000 sz=  2097168    perm      "perm           "  alo=2097168
  Chunk 41634010 sz=  1884144    free      "               "

可以通过查询x$ksmsp视图来考察Shared Pool中存在的内存片的数量,不过注意,Oracle的某些版本(如:10.1.0.2)在某些平台上(如:HP-UX PA-RISC 64-bit)查询该视图可能导致过度的CPU耗用,这是由于Bug引起的。

看一下测试,在这个测试数据库中,初始启动数据库,在x$ksmsp视图中存在11361个Chunk:

sys@NEI> select count(*) from x$ksmsp;
  COUNT(*)
----------
     11361

执行查询:

sys@NEI> select count(*) from dba_objects;
  COUNT(*)
----------
     50404

此时shared pool中的chunk数量增加:

sys@NEI> select count(*) from x$ksmsp;   
  COUNT(*)
----------
     11428

这就是由于Shared Pool中进行SQL解析,请求空间,进而导致请求free空间分配、分割,从而产生了更多、更细碎的内存Chunk。

由此可以看出,如果数据库系统中存在大量的硬解析,不停请求分配free的Shared Pool内存,除了必需的Shared Pool Latch等竞争外,还不可避免地会导致Shared Pool中产生更多的内存碎片(当然,在内存回收时,你可能看到Chunk数量减少的情况)。

继续进行一点深入的研究,首先重新启动数据库:

sys@NEI> startup force

创建一张临时表用以保存之前x$ksmsp的状态:

sys@NEI> create global temporary table e$ksmsp on commit preserve rows as
  2  select a.ksmchcom,
  3  sum(a.chunk) chunk,
  4  sum(a.recr) recr,
  5  sum(a.freeabl) freeabl,
  6  sum(a.sum) sum
  7  from (select ksmchcom,count(ksmchcom) chunk,
  8  decode(ksmchcls,'recr',sum(ksmchsiz),null) recr,
  9  decode(ksmchcls,'freeabl',sum(ksmchsiz),null) freeabl,
10  sum(ksmchsiz) sum
11  from x$ksmsp group by ksmchcom,ksmchcls) a
12  where 1=0
13  group by a.ksmchcom;
Table created.

保存当前Shared Pool状态:

sys@NEI> insert into e$ksmsp
  2  select a.ksmchcom,
  3  sum(a.chunk) chunk,
  4  sum(a.recr) recr,
  5  sum(a.freeabl) freeabl,       
  6  sum(a.sum) sum
  7  from (select ksmchcom,count(ksmchcom) chunk,
  8  decode(ksmchcls,'recr',sum(ksmchsiz),null) recr,
  9  decode(ksmchcls,'freeabl',sum(ksmchsiz),null) freeabl,
10  sum(ksmchsiz) sum
11  from x$ksmsp group by ksmchcom,ksmchcls) a
12  group by a.ksmchcom;
85 rows created.

执行查询:

sys@NEI> select count(*) from dba_objects;
  COUNT(*)
----------
     50405

比较前后Shared Pool内存分配的变化:

sys@NEI> select a.ksmchcom,a.chunk,a.sum,b.chunk,b.sum,(a.chunk-b.chunk) c_diff,(a.sum-b.sum) s_diff
  2  from
  3  (select a.ksmchcom,
  4  sum(a.chunk) chunk,
  5  sum(a.recr ) recr,
  6  sum(a.freeabl) freeabl,
  7  sum(a.sum) sum
  8  from (select ksmchcom,count(ksmchcom) chunk,
  9  decode(ksmchcls,'recr',sum(ksmchsiz),null) recr,
10  decode(ksmchcls,'freeabl',sum(ksmchsiz),null) freeabl,
11  sum(ksmchsiz) sum
12  from x$ksmsp
13  group by ksmchcom,ksmchcls) a
14  group by a.ksmchcom) a,e$ksmsp b
15  where a.ksmchcom=b.ksmchcom and (a.chunk-b.chunk) <>0;

KSMCHCOM              CHUNK        SUM      CHUNK        SUM     C_DIFF     S_DIFF
---------------- ---------- ---------- ---------- ---------- ---------- ----------
free memory             219   21339452        208   22231952         11    -892500
Heap0: KGL              656     708884        624     674580         32      34304
trigger inform            6       2620          5       2560          1         60
KGL handles            3491    1709404       3248    1596568        243     112836
modification             14      28840         13      26780          1       2060
KGLS heap              1211    1550260       1150    1467528         61      82732
obj stat memo           296      89984        284      86336         12       3648
KQR SO                  380     244880        346     226520         34      18360
kpscad: kpscsco           4        232          3        176          1         56
sql area:PLSQL           50     206980         46     190460          4      16520
PCursor                 899     963728        851     912272         48      51456
CCursor                1447    1563120       1368    1478432         79      84688
library cache          1362     130812       1299     124736         63       6076
sql area               1184    4850764       1120    4588516         64     262248
PL/SQL DIANA            340    1392640        328    1343488         12      49152
KQR PO                 2138    1074408       2016    1010576        122      63832
PL/SQL MPCODE           575    2476872        552    2376544         23     100328
CURSOR STATS             42     174048         41     169904          1       4144

18 rows selected.

简单分析一下以上结果:首先free memory的大小减小了892500(增加到另外17个组件中),这说明SQL解析存储占用了一定的内存空间;而从208增加到219,这说明内存碎片增加了,碎片增加是共享池性能下降的开始。

- The End -