Oracle Buffer Cache原理總結(一)

oracle_ace發表於2008-01-07

       Buffer cache是Oracle SGA中的重要組成部分,在自己先前的blog中對於這一塊也有過一些討論,這裡在給出一份更詳細的總結.通常資料的訪問和修改都是需要通過buffer cache來完成的,當一個server process訪問資料的時候,首先需要確定的是,我們所需要的資料在buffer cache中是否存在,如果資料在buffer中存在呢,我們還需要根據data buffer的狀態,來判斷是否進行db block gets還是consistent gets,如果資料在buffer中不存在,則我們需要在buffer cache中尋找足夠的空間來載入我們所需要的資料,如果在buffer cache中我們找不到足夠的空間,那麼我們就需要觸發DBWn程式,去寫出髒資料,用來釋放我們的buffer空間.

     Oracle通過幾個list來對buffer進行管理.其中最為突出的就是LRU List還有Dirty List,這些list上面存放的就是具體指向buffer的指標.
     
      LRU List主要就是用來維護記憶體中的buffer,按照我們LRU(Least Recently Used)的方式來進行管理.那麼針對不同的Oracle版本呢,管理的方式也不同.但是有一點需要了解的是,當資料庫初始化的時候,所有的buffer都被捕HASH到LRU List上進行管理.當我們從資料檔案中讀取資料的時候我們現在要在LRU List上面尋找free的buffer,然後將資料讀取到我們所找到的這個free buffer中.只要資料被修改了,那麼這個buffer的狀態就變為了dirty,那麼Oracle就會把這個buffer從LRU List移到Dirty List(Checkpoint Queue)中去.在Dirty List上的buffer都是一些候選的稍後會被DBWn寫出到資料檔案的buffer,那麼這裡還有一點需要注意的是:一個buffer要麼存在於LRU List上面,要麼存在於Dirty List上面,不可能同時存在於兩個List上面.

  下面的 一些概念還是需要理解的細化的:
 
  1.當Server process試圖通過掃描LRU List來尋找Free的Buffer的時候,掃描過程中會把已發現的所有Dirty buffer從LRU List移動到Dirty List(Checkpoint Queue)中去.這些buffer是我剛才說的可以候選的被DBWn程式寫出到資料檔案中的buffer.
   (Server process主動將Dirty buffer從LRU List移動到Dirty List)
 
  2.當Dirty List(Checkpoing Queue)中的Dirty Buffer量超過了一頂的閥值,那麼Server process就會通知DBWn程式寫出髒資料
   (Checkpoint Queue閥值到達,導致Server Proceess通知DBWn寫贓資料)
    這個閥值是25%,當然這也是觸發我們DBWn程式的一個條件
 
    SQL> select kvittag,kvitval,kvitdsc from x$kvit
         where kvittag='kcbldq';

    KVITTAG                                                             KVITVAL
    ---------------------------------------------------------------- ----------
    KVITDSC
    ----------------------------------------------------------------
    kcbldq                                                                   25
    large dirty queue if kcbclw reaches this

  3.如果Server process掃描了LRU超過一個閥值也沒有找到足夠的Free的buffer,這個時候也將會停止搜尋free buffer的任務然後直接通知DBWn寫髒資料來釋放記憶體空間,當然這個Server process會處於free busy wait的等待事件.這個閥值是40%,同時這還是觸發我們DBWn程式的一個條件
     (LRU掃描40%沒有找到Free buffer,Server process通知DBWn寫髒資料)  
    SQL> select kvittag,kvitval,kvitdsc from x$kvit
         where kvittag='kcbfsp';

    KVITTAG                                                             KVITVAL
    ---------------------------------------------------------------- ----------
    KVITDSC
    ----------------------------------------------------------------
    kcbfsp                                                                   40
    Max percentage of LRU list foreground can scan for free

  
  4.同時,因為Checkpoint Queue的引入,DBWn還會主動的掃描LRU List,將我們發現的Dirty Buffer從LRU List移動到checkpoing queue,掃描LRU List的範圍是25%.
    (DBWn主動掃描LRU的25%,依照結果從LRU中移動Dirty Buffer到Dirty List中,)
    SQL> select kvittag,kvitval,kvitdsc from x$kvit
         where kvittag='kcbdsp';

    KVITTAG                                                             KVITVAL
    ---------------------------------------------------------------- ----------
    KVITDSC
    ----------------------------------------------------------------
    kcbdsp                                                                   25
    Max percentage of LRU list dbwriter can scan for dirty
   
    
  5.從Oracle 8i開始呢LRU List和Dirty List分別又引入了Auxiliary List,目的是為了提高管理的效率.那麼這個List的是怎麼工作的呢?當我們的資料庫初始化的時候,BUffer首先會被HASH到LRU的Auxiliary List(Auxiliary RPL_LST)上面,那麼當buffer被使用後(注意:是使用而不是修改),會被從LRU的Auxililary List移動到LRU的Main List(MAIN RPL_LST)上面,這個時候當使用者搜尋Free buffer的時候,就可以從Auxiliary RPL_LST中開始,而DBWn主動搜尋LRU List尋找Dirty buffer的時候就會從MAIN RPL_LST開始.這樣一來就提高了我們資料庫的搜尋效率和效能
  
  現在呢,我們可以轉儲一下我們的buffer cache來看看具體的內容:
  一般我們不建議在生產環境中呢進行轉儲,因為檔案會比較大,最好我們將max_dump_file_size設定成unlimited
 
  SQL> alter session set events 'immediate trace name buffers level 4';

 我們可以來看看其中部分的資訊,包括MAIN RPL_LST,AUXILIARY RPL_LST等等,同時還有一些佇列資訊
 
  *** 2008-01-07 16:45:24.375
*** SESSION ID:(9.38) 2008-01-07 16:45:24.359
Dump of buffer cache at level 4
  (WS) size: 0 wsid:  1 state: 0
    (WS_REPL_LIST) main_prev: 68ab0740 main_next: 68ab0740 aux_prev: 68ab0748 aux_next: 68ab0748curnum: 0 auxnum: 0
cold: 68ab0740 hbmax: 0 hbufs: 0
    (WS_WRITE_LIST) main_prev: 68ab075c main_next: 68ab075c aux_prev: 68ab0764 aux_next: 68ab0764curnum: 0 auxnum: 0
    (WS_XOBJ_LIST) main_prev: 68ab0778 main_next: 68ab0778 aux_prev: 68ab0780 aux_next: 68ab0780curnum: 0 auxnum: 0
    (WS_XRNG_LIST) main_prev: 68ab0794 main_next: 68ab0794 aux_prev: 68ab079c aux_next: 68ab079ccurnum: 0 auxnum: 0
  (WS) fbwanted: 0
  (WS) bgotten: 0 sumwrt:  0 sumscan: 0
  (WS) numscan: 0 hotscan:  0 dmoves: 0
MAIN RPL_LST Queue header (NEXT_DIRECTION)[NULL]
MAIN RPL_LST Queue header (PREV_DIRECTION)[NULL]
AUXILIARY RPL_LST Queue header (NEXT_DIRECTION)[NULL]
AUXILIARY RPL_LST Queue header (PREV_DIRECTION)[NULL]
MAIN WRT_LST Queue header (NEXT_DIRECTION)[NULL]
MAIN WRT_LST Queue header (PREV_DIRECTION)[NULL]
AUXILIARY WRT_LST Queue header (NEXT_DIRECTION)[NULL]
AUXILIARY WRT_LST Queue header (PREV_DIRECTION)[NULL]
MAIN XOBJ_LST Queue header (NEXT_DIRECTION)[NULL]
MAIN XOBJ_LST Queue header (PREV_DIRECTION)[NULL]
AUXILIARY XOBJ_LST Queue header (NEXT_DIRECTION)[NULL]
AUXILIARY XOBJ_LST Queue header (PREV_DIRECTION)[NULL]
MAIN XRNG_LST Queue header (NEXT_DIRECTION)[NULL]
MAIN XRNG_LST Queue header (PREV_DIRECTION)[NULL]
AUXILIARY XRNG_LST Queue header (NEXT_DIRECTION)[NULL]
AUXILIARY XRNG_LST Queue header (PREV_DIRECTION)[NULL]
  (WS) size: 0 wsid:  2 state: 0
    (WS_REPL_LIST) main_prev: 68ab0c0c main_next: 68ab0c0c aux_prev: 68ab0c14 aux_next: 68ab0c14curnum: 0 auxnum: 0
cold: 68ab0c0c hbmax: 0 hbufs: 0
    (WS_WRITE_LIST) main_prev: 68ab0c28 main_next: 68ab0c28 aux_prev: 68ab0c30 aux_next: 68ab0c30curnum: 0 auxnum: 0
    (WS_XOBJ_LIST) main_prev: 68ab0c44 main_next: 68ab0c44 aux_prev: 68ab0c4c aux_next: 68ab0c4ccurnum: 0 auxnum: 0
    (WS_XRNG_LIST) main_prev: 68ab0c60 main_next: 68ab0c60 aux_prev: 68ab0c68 aux_next: 68ab0c68curnum: 0 auxnum: 0
  (WS) fbwanted: 0
  (WS) bgotten: 0 sumwrt:  0 sumscan: 0
  (WS) numscan: 0 hotscan:  0 dmoves: 0
MAIN RPL_LST Queue header (NEXT_DIRECTION)[NULL]
MAIN RPL_LST Queue header (PREV_DIRECTION)[NULL]
AUXILIARY RPL_LST Queue header (NEXT_DIRECTION)[NULL]
AUXILIARY RPL_LST Queue header (PREV_DIRECTION)[NULL]
MAIN WRT_LST Queue header (NEXT_DIRECTION)[NULL]
MAIN WRT_LST Queue header (PREV_DIRECTION)[NULL]
AUXILIARY WRT_LST Queue header (NEXT_DIRECTION)[NULL]
AUXILIARY WRT_LST Queue header (PREV_DIRECTION)[NULL]
MAIN XOBJ_LST Queue header (NEXT_DIRECTION)[NULL]
MAIN XOBJ_LST Queue header (PREV_DIRECTION)[NULL]
AUXILIARY XOBJ_LST Queue header (NEXT_DIRECTION)[NULL]
AUXILIARY XOBJ_LST Queue header (PREV_DIRECTION)[NULL]
MAIN XRNG_LST Queue header (NEXT_DIRECTION)[NULL]
MAIN XRNG_LST Queue header (PREV_DIRECTION)[NULL]
AUXILIARY XRNG_LST Queue header (NEXT_DIRECTION)[NULL]
AUXILIARY XRNG_LST Queue header (PREV_DIRECTION)[NULL]

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12361284/viewspace-112266/,如需轉載,請註明出處,否則將追究法律責任。

相關文章