理解Shared Pool 1,理解sharedpool
堆管理shared pool是利用堆記憶體管理方式管理的(KGH:Kernel Generic Heap).從Oracle 9i開始,可以有多個最進階堆(TOP-LEVEL HEAP),最進階堆可以分為多個副堆,副堆下面還擁有下屬副堆.堆和副堆的結構基本相同.從物理上來看,一個堆由於多個記憶體區以LINKED LIST的形式串連組成.一個記憶體區物理上使用一個GRANULE,一個記憶體區有多個CHUNK組成,所以CHUNK是HEAP的最小記憶體單位.CHUNK的使用方式可以通過X$KSMSP內部視圖查看每個堆頭上則包含了可使用的CHUNK列表和已使用的CHUNK列表.通過DUMP HEAP命令可以在追蹤檔案中觀察HEAP和EXTENT的關係alter session set events 'immediate trace name heapdump level 2';
來看一下dump檔案
sys@PROD>select * from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 11g Enterprise Edition Release 11.2.0.1.0 - Production
PL/SQL Release 11.2.0.1.0 - Production
CORE 11.2.0.1.0 Production
TNS for Linux: Version 11.2.0.1.0 - Production
NLSRTL Version 11.2.0.1.0 - Production
sys@PROD>select * from v$sgainfo where name='Granule Size';
NAME BYTES RES
-------------------------------- ---------- ---
Granule Size 4194304 No
******************************************************
HEAP DUMP heap name="sga heap(1,0)" desc=0x2002b1cc
extent sz=0xfc4 alt=124 het=32767 rec=9 flg=-126 opc=0
parent=(nil) owner=(nil) nex=(nil) xsz=0x400000 heap=(nil)
fl2=0x20, nex=(nil)
latch set 1 of 1
durations enabled for this heap
reserved granules for root 27 (granule size 4194304)
EXTENT 0 addr=0x4d000000
Chunk 4d000038 sz= 24 R-freeable "reserved stoppe"
Chunk 4d000050 sz= 4193964 R-perm "perm " alo=4193964
Chunk 4d3ffefc sz= 236 R-free " "
Chunk 4d3fffe8 sz= 24 R-freeable "reserved stoppe"
EXTENT 1 addr=0x4e000000
Chunk 4e000038 sz= 24 R-freeable "reserved stoppe"
Chunk 4e000050 sz= 212888 R-free " "
Chunk 4e033fe8 sz= 24 R-freeable "reserved stoppe"
Chunk 4e034000 sz= 1544904 perm "perm " alo=1544904
Chunk 4e1ad2c8 sz= 2436408 perm "perm " alo=455948
EXTENT 2 addr=0x4e400000
Chunk 4e400038 sz= 24 R-freeable "reserved stoppe"
Chunk 4e400050 sz= 212888 R-free " "
Chunk 4e433fe8 sz= 24 R-freeable "reserved stoppe"
Chunk 4e434000 sz= 3973960 perm "perm " alo=3973960
Chunk 4e7fe348 sz= 3976 perm "perm " alo=3976
Chunk 4e7ff2d0 sz= 3376 free " "
EXTENT 3 addr=0x4e800000
Chunk 4e800038 sz= 24 R-freeable "reserved stoppe"
Chunk 4e800050 sz= 212888 R-free " "
Chunk 4e833fe8 sz= 24 R-freeable "reserved stoppe"
Chunk 4e834000 sz= 3953996 perm "perm " alo=3953996
Chunk 4ebf954c sz= 16400 perm "perm " alo=16400
Chunk 4ebfd55c sz= 7936 perm "perm " alo=7936
Chunk 4ebff45c sz= 2980 free " "
可以看出Oracle每次以EXTENT的形式為每個"sga heap"分配空間,而每個EXTENT的大小和GRANULE有關係將EXTENT 0 中的所有Chunk相加:24+4193964+236+24=4194304-56將EXTENT 1 中的所有Chunk相加:24+212888+24+1544904+2436408=4194304-56將EXTENT 2 中的所有Chunk相加:24+212888+24+3953996+16400+7936+2980=4194304-56
這56到底是個啥?我沒百度到,我猜是EXTENT HEADER的大小
ChunkChunk以鏈條Chain的形式存在於記憶體中,每個Chunk包含Header和Body兩部分,Chunk的狀態大體上分為:FREE: 可馬上使用RECREATABLE: 可再生FREEABLE: 只有在Session或Call期間內儲存必要的對象狀態PERMANENT: 永久不可再生其中FREE和RECREATABLE狀態下的Chunk可重複使用
Free ListFree List主要用於管理閒置Chunk,並且是用Bucket管理的.從Oracle 9i開始,一個堆總共有255個Bucket,Bucket所包含的Free Chunk大小隨編號增加而遞增,各Bucket下的Free Chunk以Linked list的形式串連
在DBA實戰攻略一書中提到:同一個Bucket中的Chunk並不是按照大小排序的同樣在DBA思想天空中也有相似說明
那麼實際是什麼情況呢?FREE LISTS:
Bucket 0 size=16
Bucket 1 size=20
Chunk 4e38e234 sz= 20 free " "
Chunk 4e34738c sz= 20 free " "
Bucket 2 size=24
Chunk 4e2a0ec4 sz= 24 free " "
Chunk 4d1e8e64 sz= 24 free " "
Chunk 4e147954 sz= 24 free " "
Chunk 4e33a93c sz= 24 free " "
Chunk 4e39b61c sz= 24 free " "
Bucket 3 size=28
Chunk 4e218efc sz= 28 free " "
Chunk 4e1af51c sz= 28 free " "
Chunk 4e17b9dc sz= 28 free " "
Chunk 4e1635e4 sz= 28 free " "
Chunk 4e1ff95c sz= 28 free " "
Chunk 4e1cac74 sz= 28 free " "
Chunk 4e294914 sz= 28 free " "
Bucket 4 size=32
Bucket 5 size=36
Bucket 6 size=40
Bucket 7 size=44
Bucket 8 size=48
Bucket 9 size=52
Bucket 10 size=56
Bucket 11 size=60
Bucket 12 size=64
Bucket 13 size=68
Chunk 4d202ad4 sz= 68 free " "
Chunk 4e12a47c sz= 68 free " "
Chunk 4e390234 sz= 68 free " "
Bucket 14 size=72
截取一段,我比較腦殘,只能這麼認為如果真的不排序,那麼當去Bucket循著鏈表找Chunk的時候,假如所需大小的Chunk剛好在鏈表的最後一位,就要遍曆整條鏈表,這大大增加了持有Shared pool latch的時間從我的DUMP可以看出,也許真的沒有排序這一步,只不過由於BUCKET數量較8i大大增多,每個BUCKET中存在的Chunk多是一樣大的?真心希望知道的大神能給我解釋解釋
1.獲得shared pool latch在free list中尋找合適大小的空閑chunk。如果在擷取shared pool latch時發生了爭用,則會出現latch:shared pool等待事件。這時Oracle會一直持有shared pool latch,直到獲得所需的記憶體為止。所在記憶體片段化比較嚴重的shared pool中,進程持有shared pool latch的時間也會相應變長。
2.如果不存在合適大小的空閑chunk,則在尋找到更大的空閑chunk後分割(split)使用,分割後剩下的記憶體地區則重新登記到free list中。分割記憶體意味著記憶體中的片段開始增多。由於每個cursor所需記憶體的大小不同,所以shared pool的空閑記憶體不像buffer cache中的空閑記憶體一樣具有固定大小. 3.如果檢索了free list也沒有找到所有合適的空閑chunk,則檢索lru list。lru list上的chunk是重建(recreatable)的,而且是當前不使用的(沒有處於pin狀態).
4.如果在lru list上也沒有找到合適的chunk,且所請求的記憶體還沒有達到隱含參數_shared_pool_reserved_min_alloc的閾值,則追加分配share pool中剩餘的記憶體空間.
5.如果以上請求的記憶體均失敗,則出現ORA-4031錯誤
Shared pool的記憶體片段化是不可避免的.為了減緩Shared Pool過度片段化,如果釋放的鏈各個記憶體片在物理上是相鄰的,那麼Oracle會將其合并成一個大記憶體片。也就是說Oracle會自動定期進行記憶體的磁碟重組。
Lru ListLru List主要儲存著當前未使用而且可以重建的Chunk,當繪畫在Free list中找不到空閑Chunk時,則會在Lru List中尋找UNPINNED RECREATABLE CHUNKS (lru first):
Chunk 517a621c sz= 32 recreate "fixed allocatio" latch=0x2000fc90
Chunk 4ebbd94c sz= 332 recreate "KGLHD " latch=(nil)
Chunk 4eb9c7f8 sz= 332 recreate "KGLHD " latch=(nil)
Chunk 4eb66c68 sz= 332 recreate "KGLHD " latch=(nil)
Chunk 4eb6aaa4 sz= 332 recreate "KGLHD " latch=(nil)
Chunk 4eb3dadc sz= 332 recreate "KGLHD " latch=(nil)
Chunk 4eb3fde0 sz= 332 recreate "KGLHD " latch=(nil)
Chunk 4eb2e7fc sz= 332 recreate "KGLHD " latch=(nil)
Chunk 4efed6ec sz= 40 recreate "fixed allocatio" latch=0x4ff04cd8
Chunk 4eb283ec sz= 540 recreate "KQR PO " latch=0x4ff04cd8
Chunk 4eb28608 sz= 540 recreate "KQR PO " latch=0x4ff04cd8
Chunk 4eb27398 sz= 32 recreate "fixed allocatio" latch=0x4ff04920
Chunk 4eb2692c sz= 32 recreate "fixed allocatio" latch=0x2000e4cc
Chunk 4eb258f4 sz= 32 recreate "fixed allocatio" latch=0x4ff04570
Reserved PoolOracle是從7.1.5版本開始支援保留池的,保留池的設計目的是為了在共用池片段化很嚴重的時候,還能夠有一部分保留空間,用於較大的記憶體配置。通過shared_pool_reserved_size來設定保留池大小,一般可以不設定,預設是5%保留池使用條件1.在共用池freelist中找不到足夠大的Chunk2.在lru list上也沒有找不到合適的chunk或可重建的recreatable且狀態為unpin的chunk3.分配的內容要大於_SHARED_POOL_RESERVED_MIN_ALLOC(預設值為4400B),就是說超過這個值得記憶體配置才被認為是大記憶體配置一些常用的系統對象往往在4000-4400B,因此在片段化很嚴重且經常由於ORA-04031導致宕機的系統中,將這個參數設定得小一點(比如4000或3800)是十分有必要的select indx from x$ksppi where upper(ksppinm) ='_SHARED_POOL_RESERVED_MIN_ALLOC';
INDX
----------
153
sys@PROD>select ksppstvl from x$ksppsv where indx =153;
KSPPSTVL
----------------------------------------------------------------------------------------------------
4400
select indx from x$ksppi where upper(ksppinm) ='_SHARED_POOL_RESERVED_PCT';
INDX
----------
152
select ksppstvl from x$ksppsv where indx =152;
KSPPSTVL
----------------------------------------------------------------------------------------------------
5
保留池是否過小?
select REQUEST_MISSES from v$shared_pool_reserved;
這個查詢,查詢出在保留區申請不到空間的次數(request_failures),我們希望它是0,如果大於0,就要視情況考慮增大保留區大小
保留池是否過大?
reuest_misses為0且沒有增長
Free space ≥ SHARED_POOL_RESERVED_SIZE Minimum
需要注意的是保留池會隨著shared pool擴大而擴大,且即使縮小Shared Pool後也無法縮小,Flush也沒用