shared pool之三:library cache結構/library cache object的結構-dump LibraryHandle

還不算暈發表於2014-01-04

Library cache結構

Library cache最主要的功能就是存放使用者提交的SQL語句,SQL語句相關的解析樹(解析樹也就是對SQL語句中所涉及到的所有物件的展現)--->共享SQL區(shared SQL areas),私有SQL區(private SQLareas,如果配置了共享伺服器),執行計劃,使用者提交的PL/SQL程式塊(包括匿名程式塊,儲存過程,包,函式等)以及它們轉換後能夠被Oracle執行的程式碼等,為了對這些記憶體結構進行管理,library cache中還存放了很多控制結構,包括lock,pin,dependency table,11G中的mutex等。
Library cache需要解決三個問題:
(1).快速定位的問題:Library cache中物件眾多,Oracle如何管理這些物件,以便服務程式可以迅速找到他們需要的資訊。比如某個服務程式需要迅速定位某個SQL是否存在於Librarycache中。---Oracle利用hash table結構來解決library cache中快速定位的問題
(2).關係依賴的問題:Library cache中的物件存在複雜的依賴關係,當某個objec失效時,可以迅速將依賴其的物件也置為失效狀態。比如某個表發生了結構變化,依賴其的SQL語句需要重新解析。---LCO中dependency table
(3).併發控制的問題:Library cache中必須有一個併發控制的機構,比如鎖機制,來管理大量共享物件的併發訪問和修改的問題,比如某個SQL在重新編譯的同時,其所依賴的物件不能被修改。----LATCH LOCK PIN

Library cache由一個hash表組成,hash表是由hash buckets組成的陣列。
每個hash bucket都是包含library cache handle的一個雙向連結串列。
library cache handle指向library cache object和一個引用列表。
library cache 物件進一步分為:依賴表、子表、授權表等
同一個SQL語句,HASH值相同,放在同一個library cache handle--如繫結變數,是用同一個library cache handle下不同的的子游標。不同的SQL語句,HASH值相同放在同一hash bucket的不同library cache handle。

Hash 演算法

Oracle在內部管理中大量的使用到了hash,使用hash的目的就是為了快速查詢和定位.
對數值進行hash運算,產生一個索引號,然後根據索引號將數值放置到相應的hash bucket中去.
根據hash運算的法則,會產生多個索引號,每一個索引號對應一個hash bucket(一個數值列).
在尋找數值的時候,將搜尋的數值進行hash,產生一個索引號,那麼這個數值一定在這個索引號對應的 hash bucket中,於是直接跳轉到這個hash bucket中進行遍歷。這樣在定位資料的時候,就能夠大大的減少遍歷的數量。

hash bucket:庫快取中就是使用hash bucket來管理的

1、首先根據shared_pool_size指定的尺寸來自動計算hash bucket的個數
2、每個hash bucket後面都串聯著多個控制程式碼
    控制程式碼描述了library cache裡面的物件的一些屬性,包括名稱、標記、指向物件所處的記憶體地址的指標


library cache handle:-----OBJECT Handle

 一個handle管理著一個library cache object,handle對LCO起到指標作用。
Library cache中所有物件的訪問是通過利用library cache handle來實現的
當一個程式請求library cache object, librarycache manager就會應用一個hash 演算法,從而得到一個hash 值,根據相應的hash值到相應的hash bucket中去尋找。
  如果library cache object在記憶體中,那麼這個library cache handle就會被找到。有時候,當shared pool不夠大,library cache handle會保留在記憶體中,然而library cache heap由於記憶體不足被age out,這個時候我們請求的object heap就會被過載。最壞的情況下,library cache handle在記憶體中沒有找到,這個時候就必須分配一個新的library cachehandle,同時object heap也會被載入到記憶體中。

###############




library cache object的結構: --LCO

見上圖,主要儲存SQL的實際資訊,包括:
dependency table --當前LCO依賴的其它LCO資訊,如SQL語句依賴的表、檢視等。

1.Chile table----儲存當前LCO的子LCO資訊

一個LCO會有多個子LCO---多版本問題。---一條SQL至少有一個parent cursor 和 child cursor。
存在不同版本SQL可能是:不同使用者執行相同SQL檔案的SQL.--也可能是BUG。

SQL語句文字一樣-HASH值一樣,執行計劃不一樣的情況有:--多版本
1.不同使用者下有同名的表,不同的使用者執行查詢此表操作,就會出現不同執行計劃。
2.繫結變數時,如果繫結變數的字串(詳見:繫結變數分級)變化達到一定程度,執行計劃也會不一樣

HIGH VERSION高版本的SQL語句有多個子LCO,每個子HANDLE對應一個子LCO
。---parent cursor 裡對應的所有child  cursor的指標都會儲存在child table裡面。--parent cursor和child cursor都是用library cache object handle 儲存在Library Cache裡的。---結構一樣
當子LCO數量很多--SQL版本數(VERSION COUNT)很高,會話掃描BUCKET時間變長,持有latch:library cache時間也變長,定位到具體的child sql cursor時間相應變長(順序掃描HANDLE),latch:library cache爭用的概念增加。
檢視SQL版本資訊:
BYS@ bys3>select * from (select version_count,sql_id,sql_text from v$sqlarea order by version_count desc) where rownum<5 ;

BYS@ bys3>select version_count,sql_id,sql_text from v$sqlarea where sql_text like 'select * from bys.dept';
VERSION_COUNT SQL_ID        SQL_TEXT
------------- ------------- ------------------------------
            1 f4yk5kundsxfd select * from bys.dept

2.data blocks ---儲存SQL語句、執行計劃、執行文字等資訊。

ORACLE通過地址指向儲存 這些資訊的HEAP /CHUNK。HEAP 6儲存著SQL執行計劃。
ORACLE 10.2.0.4開始可以通過dbms_shared_pool.purge 包清理HEAP 6中執行計劃。

3.dependency table

指向本物件所依賴的物件,比如:select * from emp這個cursor的物件,依賴emp這個表,這裡指向了emp這個表的handle。
####################################################3

通過x$kglob找出SQL語句父遊標地址,並DUMP library cache,在TRACE檔案中父遊標的地址中找到SQL語句。

會話1
SYS@ bys3>select * from bys.dept;
SYS@ bys3>col KGLNAOBJ for a40
SYS@ bys3>select kglhdadr,kglhdpar,kglnaobj,kglobhd0 from x$kglob where kglnaobj like 'select * from bys.dept%';
KGLHDADR KGLHDPAR KGLNAOBJ                       KGLOBHD0
-------- -------- ------------------------------ --------
23ACB574 248344B8 select * from bys.dept         242B7D1C   --23ACB574子游標地址
248344B8 248344B8 select * from bys.dept         23FE4684   --248344B8父遊標地址,父遊標heap 0地址-其實是描述符-23FE4684

 
select KGLHDADR,KGLHDPAR,KGLNAOBJ,KGLOBHD0 from x$kglob where kglnaobj like 'select * from bys.dept%' and KGLHDADR<>KGLHDPAR ;   查出子游標
select KGLHDADR,KGLHDPAR,KGLNAOBJ,KGLOBHD0 from x$kglob where kglnaobj like 'select * from bys.dept%' and KGLHDADR=KGLHDPAR ;  查出父遊標

SYS@ bys3>select KSMCHPTR,KSMCHCOM,KSMCHCLS,KSMCHSIZ from x$ksmsp where KSMCHPAR='23FE4684';    --通過上一步查出的 heap 0描述符找到檢視父遊標所在CHUNK地址大小描述狀態
KSMCHPTR KSMCHCOM         KSMCHCLS   KSMCHSIZ
-------- ---------------- -------- ----------
241D3A44 KGLH0^a8dc75cd   recr           4096

新開啟一個會話:DUMP library cache並查詢SQL語句。
SYS@ bys3>alter session set events 'immediate trace name heapdump level 2050';
SYS@ bys3>select value from v$diag_info where name like 'De%';
VALUE
----------------------------------------------------------------------------------------------------
/u01/diag/rdbms/bys3/bys3/trace/bys3_ora_31638.trc
#################
VI中查詢:  在241D3A44這個地址開始的這個 Chunk中找到了SQL語句
 Chunk 241d3a44 sz=     4096    recreate  "KGLH0^a8dc75cd "  latch=(nil)
     ds 23fe4684 sz=     4096 ct=        1
Dump of memory from 0x241D3A44 to 0x241D4A44
241D3A40          80001001 241D2A44 00000000      [....D*.$....]
241D3A50 00000000 00000000 00000000 000A0FFF  [................]

………………

  Chunk 2405e530 sz=     4096    recreate  "SQLA^bf04295e  "  latch=(nil)
Dump of memory from 0x2405E530 to 0x2405F530
2405E530 80001001 2405E164 2526A6EC 237A8414  [....d..$..&%..z#]
………………
2405E680 00000000 00000000 00000000 00000000  [................]
2405E690 00000000 00000000 F4A4D8E8 735DAFAF  [..............]s]
2405E6A0 00000000 00000049 2405E65C 11390064  [....I...\..$d.9.]
2405E6B0 01748F8F 18150001 407EC500 0A8A0500  [..t.......~@....]
2405E6C0 00020103 00090203 093A0000 1E070604  [..........:.....]
2405E6D0 F0836A0A A8E0F183 E036E426 83E426A8  [.j......&.6..&..]
2405E6E0 03F383F5 02030302 008E0000 00000025  [............%...]
2405E6F0 2405E6A4 110B3B04 656C6573 2A207463  [...$.;..select *]
2405E700 6F726620 7962206D 65642E73 00257470  [ from bys.dept%.]

2405E710 0000003D 2405E6EC 110B3B34 0000000D  [=......$4;......]
2405E720 00000801 00170040 00010369 00000018  [....@...i.......]
…………
###########################################################################

通過x$kglob找出SQL語句子游標地址及堆6地址,並DUMP library cache,在TRACE檔案中檢視的內容。

堆0 heap 0 --屬於父遊標-library cache handle,子游標裡也有兩個堆,堆0 存放指向堆6的地址
SYS@ bys3>select * from bys.dept;
SYS@ bys3>col KGLNAOBJ for a25
SYS@ bys3>select kglhdadr,kglhdpar,kglnaobj,KGLOBHS0,kglobhd0,KGLOBHS6,KGLOBHD6 from x$kglob where kglnaobj like 'select * from bys.dept%';
KGLHDADR KGLHDPAR KGLNAOBJ                    KGLOBHS0 KGLOBHD0   KGLOBHS6 KGLOBHD6
-------- -------- ------------------------- ---------- -------- ---------- --------
2358B76C 23D0705C select * from bys.dept          4348 2526A068       4060 243F2238
23D0705C 23D0705C select * from bys.dept          4516 23D65B44          0 00
父遊標LibraryHandle 地址KGLHDPAR:23D0705C 子游標LibraryHandle地址KGLHDADR:2358B76C,

父遊標堆0描述KGLOBHD0:23D65B44,子游標堆0描述:2526A068,子游標堆6描述KGLOBHD6:243F2238

這一點可以DUMP檢視, alter session set events 'immediate trace name heapdump_addr level 2,addr0x23b31e80‘; 類似以下:desc=0x23b31e80這種就可以與上面查出的KGLOBHD0欄位資訊對應--我這是後來增加的,沒法對應上了。

******************************************************
HEAP DUMP heap name="KGLH0^1020848"  desc=0x23b31e80
 extent sz=0xff4 alt=32767 het=28 rec=9 flg=2 opc=0
 parent=0x200010b4 owner=0x23b31e4c nex=(nil) xsz=0xfe4 heap=(nil)
 fl2=0x26, nex=(nil), dsxvers=1, dsxflg=0x0
 dsx first ext=0x240b19c4
EXTENT 0 addr=0x240b19c4
  Chunk 240b19cc sz=       44    p

SYS@ bys3>select KSMCHPTR,KSMCHCOM,KSMCHCLS ,KSMCHSIZ from x$ksmsp where  KSMCHPAR='23D65B44';
--通過上一步查出的父遊標heap 0描述符找到檢視父遊標所在CHUNK地址大小描述狀態
KSMCHPTR KSMCHCOM         KSMCHCLS   KSMCHSIZ
-------- ---------------- -------- ----------
243F1D68 KGLH0^a8dc75cd   recr           4096
SYS@ bys3>select KSMCHPTR,KSMCHCOM,KSMCHCLS ,KSMCHSIZ from x$ksmsp where  KSMCHPAR='2526A068';
--通過上一步查出的子游標heap 0描述符找到檢視子游標堆0所在CHUNK地址大小描述狀態:
KSMCHPTR KSMCHCOM         KSMCHCLS   KSMCHSIZ
-------- ---------------- -------- ----------
23FDD830 KGLH0^a8dc75cd   recr           4096  --KGLH0^a8dc75cd   --H0 heap 0
SYS@ bys3>select KSMCHPTR,KSMCHCOM,KSMCHCLS ,KSMCHSIZ from x$ksmsp where  KSMCHPAR='243F2238';
--通過上一步查出的子游標heap 6描述符,找到檢視子游標堆6所在CHUNK地址大小描述狀態
KSMCHPTR KSMCHCOM         KSMCHCLS   KSMCHSIZ
-------- ---------------- -------- ----------
23FDB830 SQLA^a8dc75cd    recr           4096   --SQLA^a8dc75cd -SQL area

SYS@ bys3>col sql_text for a25
SYS@ bys3>select sql_id,hash_value,address,child_address,sql_text from v$sql where sql_text like 'select * from bys.dept%';
--檢視SQL語句的SQL_ID,HASH_VALUE ADDRESS  CHILD_AD等資訊,與下面DUMP的資訊對照。
SQL_ID        HASH_VALUE ADDRESS  CHILD_AD SQL_TEXT
------------- ---------- -------- -------- -------------------------
f4yk5kundsxfd 2833020365 23D0705C 2358B76C select * from bys.dept
新會話DUMP
SYS@ bys3>alter session set events 'immediate trace name library_cache level 16';
Session altered.
level 1,轉儲library cache統計資訊;level 2,轉儲hash table 概要
level 4,轉儲library cache物件基本資訊;level 4,轉儲library cache物件詳細資訊
level 16,增加了heap sizes資訊。
  
SYS@ bys3>select value from v$diag_info where name like 'De%';
VALUE
---------------------------------------------------

/u01/diag/rdbms/bys3/bys3/trace/bys3_ora_22403.trc

#########################################
Bucket: #=30157 Mutex=0x26ab5658(2e0000, 78, 0, 6)
  LibraryHandle:  Address=0x23d0705c Hash=a8dc75cd LockMode=0 PinMode=0 LoadLockMode=0 Status=VALD
##Address=0x23d0705c與x$kglob.KGLHDPAR父遊標地址相符.Hash=a8dc75cd與x$ksmsp.KSMCHCOM相符,轉換為10進位制則與v$sql.HASH_VALUE相符;

    ObjectName:  Name=select * from bys.dept    ##執行的語句內容,與x$kglob.KGLNAOBJ
      FullHashValue=2cd147d1d9b8972be27a4596a8dc75cd Namespace=SQL AREA(00) Type=CURSOR(00) Identifier=2833020365 OwnerIdn=0
      ##Identifier=2833020365與v$sql.HASH_VALUE相符,Namespace=SQL AREA(00) SQL區域
    Statistics:  InvalidationCount=0 ExecutionCount=1 LoadCount=2 ActiveLocks=0 TotalLockCount=1 TotalPinCount=1
    Counters:  BrokenCount=1 RevocablePointer=1 KeepDependency=1 Version=0 BucketInUse=0 HandleInUse=0 HandleReferenceCount=0
    Concurrency:  DependencyMutex=0x23d070c4(0, 1, 0, 0) Mutex=0x23d07120(46, 39, 0, 6)
    Flags=RON/PIN/TIM/PN0/DBN/[10012841]
    WaitersLists:
      Lock=0x23d070b4[0x23d070b4,0x23d070b4]
      Pin=0x23d070a4[0x23d070a4,0x23d070a4]
      LoadLock=0x23d070e8[0x23d070e8,0x23d070e8]
    Timestamp:  Current=01-04-2014 18:03:50  ##時間戳
    HandleReference:  Address=0x23d0718c Handle=(nil) Flags=[00]
    ReferenceList:
      Reference:  Address=0x23fdcb14 Handle=0x2345e2a8 Flags=ROD[21]
    LibraryObject:  Address=0x243f1dc8 HeapMask=0000-0001-0001-0000 Flags=EXS[0000] Flags2=[0000] PublicFlags=[0000]
      DataBlocks:
        Block:  #='0' name=KGLH0^a8dc75cd pins=0 Change=NONE
          Heap=0x23d65b44 Pointer=0x243f1e1c Extent=0x243f1d84 Flags=I/-/P/A/-/-
          FreedLocation=0 Alloc=1.546875 Size=3.988281 LoadTime=4405191980
      ChildTable:  size='16'
        Child:  id='0' Table=0x243f2d18 Reference=0x243f2390 Handle=0x2358b76c    ##子指標
      Children:

        Child:  childNum='0'
          LibraryHandle:  Address=0x2358b76c Hash=0 LockMode=0 PinMode=0 LoadLockMode=0 Status=VALD
##子游標LibraryHandle地址Address=0x2358b76c,與x$kglob.KGLHDADR子游標地址相符

            Name:  Namespace=SQL AREA(00) Type=CURSOR(00)
            Statistics:  InvalidationCount=0 ExecutionCount=1 LoadCount=1 ActiveLocks=0 TotalLockCount=1 TotalPinCount=2
            Counters:  BrokenCount=1 RevocablePointer=1 KeepDependency=0 Version=0 BucketInUse=0 HandleInUse=0 HandleReferenceCount=0
            Concurrency:  DependencyMutex=0x2358b7d4(0, 0, 0, 0) Mutex=0x23d07120(46, 39, 0, 6)
            Flags=RON/PIN/PN0/EXP/CHD/[10012111]
            WaitersLists:
              Lock=0x2358b7c4[0x2358b7c4,0x2358b7c4]
              Pin=0x2358b7b4[0x2358b7b4,0x2358b7b4]
              LoadLock=0x2358b7f8[0x2358b7f8,0x2358b7f8]
            ReferenceList:
              Reference:  Address=0x243f2390 Handle=0x23d0705c Flags=CHL[02]
            LibraryObject:  Address=0x23fdd890 HeapMask=0000-0001-0001-0000 Flags=EXS[0000] Flags2=[0000] PublicFlags=[0000]
              Dependencies:  count='1' size='16' table='0x23fde7a4'
                Dependency:  num='0'
                  Reference=0x23fddcb0 Position=18 Flags=DEP[0001]
                  Handle=0x2433a460 Type=TABLE(02) Parent=BYS.DEPT
              ReadOnlyDependencies:  count='1' size='16'
                ReadDependency:  num='0' Table=0x23fde7f0 Reference=0x23fddc1c Handle=0x2345e2a8 Flags=DEP/ROD/KPP[61]
              Accesses:  count='1' size='16'
                Dependency:  num='0' Type=0009
              DataBlocks:
                Block:  #='0' name=KGLH0^a8dc75cd pins=0 Change=NONE
                  Heap=0x2526a068 Pointer=0x23fdd8e4 Extent=0x23fdd84c Flags=I/-/-/A/-/-
                  #####Heap=0x2526a068子游標堆0的地址,與x$kglob.KGLOBHD0相符

                  FreedLocation=0 Alloc=1.382812 Size=3.964844 LoadTime=4405191980
                Block:  #='6' name=SQLA^a8dc75cd pins=0 Change=NONE
                  Heap=0x243f2238 Pointer=0x23fdc624 Extent=0x23fdb84c Flags=I/-/-/A/-/E
                  ##Heap=0x243f2238這個就是子游標堆6的地址,與x$kglob.KGLOBHD6相符

                  FreedLocation=0 Alloc=3.785156 Size=3.964844 LoadTime=0
            NamespaceDump:  --子游標資訊
              Child Cursor:  Heap0=0x23fdd8e4 Heap6=0x23fdc624 Heap0 Load Time=01-04-2014 18:03:50 Heap6 Load Time=01-04-2014 18:03:50
    NamespaceDump:      
      Parent Cursor:  sql_id=f4yk5kundsxfd parent=0x243f1e1c maxchild=1 plk=n ppn=n
   ##父遊標,sql_id=f4yk5kundsxfd與v$sql.sql_id相符,

###############################################

DUMP SQL語句父子游標的堆0和堆6

SYS@ bys3>select kglhdadr,kglhdpar,kglnaobj,KGLOBHS0,kglobhd0,KGLOBHS6,KGLOBHD6 from x$kglob where kglnaobj like 'select * from bys.test%';
KGLHDADR KGLHDPAR KGLNAOBJ                    KGLOBHS0 KGLOBHD0   KGLOBHS6 KGLOBHD6
-------- -------- ------------------------- ---------- -------- ---------- --------
240EDA68 239948A4 select * from bys.test          4348 23B31E80       4060 245908B0
239948A4 239948A4 select * from bys.test          4500 241368BC          0 00

alter session set events 'immediate trace name heapdump_addr level 2,addr 0x241368BC';  --使用這樣的語句把父子游標的堆0、堆6全DUMP出來。

我把三個DUMP檔案的開頭貼一下:

父遊標堆0:desc=欄位與x$kglob.KGLOBHD0對應,heap name="KGLH0^   堆名字也表明是堆0
******************************************************
HEAP DUMP heap name="KGLH0^1020848"  desc=0x241368bc
 extent sz=0xff4 alt=32767 het=28 rec=9 flg=2 opc=0
 parent=0x200010b4 owner=0x24136888 nex=(nil) xsz=0xfe4 heap=(nil)
 fl2=0x26, nex=(nil), dsxvers=1, dsxflg=0x0
 dsx first ext=0x245903fc
EXTENT 0 addr=0x245903fc
  Chunk 24590404 sz=       44    perm      "perm           "  alo=44
Dump of memory from 0x24590404 to 0x24590430

子游標堆0:--我的版本是11.2.0.4,有的版本DUMP出來的heap name="CCURSE,,比較直觀說明是子游標。。這 裡只能通過desc=欄位與x$kglob.KGLOBHD6對應

******************************************************
HEAP DUMP heap name="KGLH0^1020848"  desc=0x23b31e80
 extent sz=0xff4 alt=32767 het=28 rec=9 flg=2 opc=0
 parent=0x200010b4 owner=0x23b31e4c nex=(nil) xsz=0xfe4 heap=(nil)
 fl2=0x26, nex=(nil), dsxvers=1, dsxflg=0x0
 dsx first ext=0x240b19c4
EXTENT 0 addr=0x240b19c4
  Chunk 240b19cc sz=       44    perm      "perm           "  alo=44

子游標堆6:  --從DUMP名字也可以看出是存放SQL執行計劃等的SQL區域。--有的版本DUMP出來這裡顯示的heapname="SQL AREA,我這個11.2.0.4版本上看就這樣了。。

******************************************************
HEAP DUMP heap name="SQLA^1020848"  desc=0x245908b0
 extent sz=0xff4 alt=32767 het=184 rec=0 flg=2 opc=2
 parent=0x200010b4 owner=0x245907e4 nex=(nil) xsz=0xfe4 heap=(nil)
 fl2=0x27, nex=(nil), dsxvers=1, dsxflg=0x0
 dsx first ext=0x24b12c54
EXTENT 0 addr=0x24b12c54
  Chunk 24b12c5c sz=       44    perm      "perm           "  alo=44

相關文章