The Shared Pool
The Shared Pool 在 SGA 中是 SIZE 较大的一个部分 . 有很多 DBA 没搞明白 Shared Pool 是用来做什么的 , 不知道怎么定 Shared Pool 的合适的 SIZE. 就随意的将它的 SIZE 搞得很大 . 有时候可能是不够大 , 但更多的时候是在浪费内存空间 . 而且太大的 Shared Pool 会影响性能 .
块 (Chunk):
要更好的理解 Shared Pool, 得对 X$KSMSP 表多做点研究 . 这个表中的每一个记录行对应的是 Shared Pool 内存中的一个 Chunk( 块 ).
SQL> select ksmchcom, ksmchcls, ksmchsiz from x$ksmsp;
KSMCHCOM KSMCHCLS KSMCHSIZ
---------------- -------- ----------
KGL handles recr 496
PL/SQL MPCODE recr 1624
dictionary cach freeabl 4256
free memory free 1088
library cache freeabl 568
library cache recr 584
multiblock rea freeabl 2072
permanent memor perm 1677104
row cache lru recr 48
session param v freeabl 2936
sql area freeabl 2104
sql area recr 1208
上面的是对这个表查询的例子 .( 对整个表的查询有 5726 行左右的记录 )
在每个 Shared Pool Chunk 已经分配好之后 , 代码将语句转化并使其有作用的这一过程实际上就称为一次分配 . 这个语句可以在 X$KSMSP 表中的 KSMCHCOM 字段看到 , 描述分配的内存 Chunk. 每一个 Chunk 都要比它所包含的对象要大 , 因为每个 Chunk 都有多出来 16 字节的头信息用于存储确认 Chunk 的类型、类别和大小 SIZE 还有用于 Shared Pool 管理的链接指针 .
内存 Chunk 主要有四种类别 , 可以从 X$KSMSP 表中的 KSMCHCLS 看到 .
free: 这种类别的 Chunk 称为 Free Chunk. 它不包含有效的对象 , 可以自由分配 .
recr: 可重建的 Chunk(Recreatable Chunk), 这种 Chunk 有包含对象 , 而这些对象在必要的时候是可以临时被删除并在有需要的情况下进行重建 . 一个例子 , 包含 Shared SQL Statements 的 Chunks 就可以重建
freeabl: 可释放的 Chunk(Freeabl Chunk), 这种 Chunk 也有包含对象 , 这些对象在一个 session 的生存期间是经常可用的而在 session 断掉之后就不可用 . 这些 Chunks 可以在 session 断开之前进行释放 , 可以部分释放也可以全部释放 .Freeable Chunk 是不能临时被删除的 , 因为它是不可重建的 .
perm: 永久性的内存 Chunk(Permanent memory Chunk). 它包含的对象是不能被释放的 , 是永久存在于内存中的 . 一些大的永久性的内存 Chunk 内部也包含一定量的 free space. 可以根据需要释放给 shared poo.
select
ksmchcom contents,
count(*) chunks,
sum(decode(ksmchcls, 'recr', ksmchsiz)) recreatable,
sum(decode(ksmchcls, 'freeabl', ksmchsiz)) freeable,
sum(ksmchsiz) total
from
sys.x_$ksmsp
where
inst_id = userenv('Instance') and
ksmchcls not like 'R%'
group by
ksmchcom
KSMCHCOM CHUNKS RECR FREEABL TOTAL
---------------- ---------- ---------- ---------- ----------
KGFF heap 6 1296 2528 3824
KGK contexts 2 2400 2400
KGK heap 2 1136 1136
KGL handles 571 178616 178616
KQLS heap 404 87952 524888 612840
PL/SQL DIANA 274 42168 459504 501672
PL/SQL MPCODE 57 14560 88384 102944
PLS cca hp desc 1 168 168
PLS non-lib hp 1 2104 2104
character set m 5 23504 23504
dictionary cach 108 223872 223872
fixed allocatio 9 360 360
free memory 185 614088
kzull 1 48 48
library cache 1612 268312 356312 624624
multiblock rea 1 2072 2072
permanent memor 1 1677104
reserved stoppe 2 48
row cache lru 24 1168 1168
session param v 8 23488 23488
sql area 983 231080 1303792 1534872
table columns 19 18520 18520
table definiti 2 176 176
上面这个查询可以得到 Shared Pool 中所有 Chunks 的类型 , 类别和大小 SIZE 等相关信息 . 上面只列出部分记录 .
Free Lists:
Shared Pool 中的 Free Chunks, 于它们的大小为基准被组织成 Free Lists 或者 Buckets. 下面的一张表是 Bucket 号和 Free Chunks SIZE 的对应关系 :
用下面这个脚本可以查询到 Chunks 数和每个 Free List 中的 Free Space 量 .
select
decode(sign(ksmchsiz - 80), -1, 0, trunc(1/log(ksmchsiz - 15, 2)) - 5)
bucket,
sum(ksmchsiz) free_space,
count(*) free_chunks,
trunc(avg(ksmchsiz)) average_size,
max(ksmchsiz) biggest
from
sys.x_$ksmsp
where
inst_id = userenv('Instance') and
ksmchcls = 'free'
group by
decode(sign(ksmchsiz - 80), -1, 0, trunc(1/log(ksmchsiz - 15, 2)) - 5)
BUCKET FREE_SPACE FREE_CHUNKS AVERAGE_SIZE BIGGEST
---------- ---------- ----------- ------------ ----------
0 166344 3872 42 72
1 32208 374 86 96
4 928 1 928 928
6 11784 4 2946 3328
当一个进程需要 Shared Pool Memory 分配一个 Chunk 时 , 它首先会到 Free Lists 中查找与它所需的 SIZE 匹配的 Chunk. 如果跟所需的 SIZE 没有确切相符的 Chunk 可以分配则会继续在 Free Lists 中寻找一个更大的 Chunk. 如果找到的 Chunk 有 24 字节或者更多 , 则这个 Chunk 将会被分裂开来使用 , 将其余的 Free Space 部分返还到 Free Lists 中 . 如果上面的都找不到 , 则会从一个非空的 Free Lists 中找一个最小的 Chunk 给它使用 . 最后的方式是以 LRU 机制对 Free Lists 进行描述
Free Lists 的描述 , 管理和 Chunk 的分配都是在 Shared Pool Lathes 的保护下进行的 . 如果 Shared Pool 包含有大量的小的 Free Chunks 时 , 在对这个特殊的 Free Lists 进行描述时 ,Shared Pool Lathes <SPAN style="FONT-FAMILY: 宋体; mso-ascii-font-family: 'Courier New'; mso-hansi-font-family: 'Courier New'; mso-bidi-font-family: 'Courier New'"