Oracle Buffer Cache原理總結(一)

[url]http://space.itpub.net/?uid-12361284-action-viewspace-itemid-112266[/url]
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]
發佈了187 篇原創文章 · 獲贊 0 · 訪問量 9354
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章