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的生存期間是經??捎玫亩趕ession斷掉之后就不可用.這些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將會被占有比較長的一段時間.實際上,經常出現的Shared Pool Lathes的競爭和等待就是因為包含了大量的小的Free Chunks.所以增加Shared Pool 的SIZE并不能減少Shared Pool Lathes Contention而且還會使得這個競爭更加嚴重,這就是前面提到的將Shared Pool的SIZE設為很大并不一定會提高性能原因.
LRU Lists:
假如一個進程沒辦法從Shared Pool Free Lists中獲得一個Free Chunk,則它會從Shared Pool中刪除一個包含有Recreatable對象的Chunks來釋放足夠大的Chunks滿足自己的使用.
Recreatable Chunks有兩個種類:一種是Pinned在內存中的,一種是沒有Pinned在內存中的.Pinned在內存中的Chunks跟用DBMS_SHARED_POOL.KEEP執行來KEEP在Shared Pool中是不一樣的. DBMS_SHARED_POOL.KEEP是需要DBA來干預執行的,并且只能放在library cache中.而Pinned Chunks是自動執行的,它在Chunks包含正在使用的對象時就會自動被pinned在Shared Pool中.Pinned Recreatable Chunks是不能釋放空間的,而Unpinned Recreatable Chunks是可以釋放出來的.
在Shared Pool中,Unpinned Chunks被組織成兩個Lists,它們都是以LRU機制來排列的.分別被稱為臨時的LRU List和循環的LRU List. Chunks在Unpinned時放在MRU(most recently used)的最后面,在它們pinned時將會從這個MRU List中刪除.
在一個進程需要新分配一部分Shared Pool Memory內存時,Chunks也會從LRU List的最尾端刪除.Chunks以每8個chunks為一個集而被flushed(暫時說為清空)-----首先是從臨時的LRU List,然后再從循環的LRU List. Chunks是在不考慮SIZE的大小并且以LRU機制被flushed的.有一些Chunks是不能被 flushed的,如用DBMS_SHARED_POOL.KEEP執行后的包含library cache 對象的Chunks是不能被 flushed.這些Chunks通過pinned方式來代替被刪除.
Unpinned Recreatable Chunks兩種類型的LRU Lists: 臨時的LRU List和循環的LRU List的長度可以從fixed表X$KGHLU查詢到,還有已經flush掉的Chunks數,由于pinned和unpinned而加入到LRU List或者是從LRU List刪除的Chunks數.從X$KGHLU表也可以知道LRU Lists被flushed完全但不成功(不理解)的次數和最近一次請求Chunk失敗的所需要Chunk SIZE.具體看下面的語句:
column kghlurcr heading "RECURRENTCHUNKS"
column kghlutrn heading "TRANSIENTCHUNKS"
column kghlufsh heading "FLUSHEDCHUNKS"
column kghluops heading "PINS ANDRELEASES"
column kghlunfu heading "ORA-4031ERRORS"
column kghlunfs heading "LAST ERRORSIZE"
select
kghlurcr,
kghlutrn,
kghlufsh,
kghluops,
kghlunfu,