ORACLE buffer cache 原理 --LRU連結串列(參照學習:oracle核心技術揭秘)

lff1530983327發表於2016-08-31

OBJ-Q物件列表在合併IO的過程中起了很大作用,因為髒塊在從CKPT-Q中移到物件列表的時候會將不同物件的塊鏈在一起,這樣更容易找到連續的塊進行合併。


LRU連結串列一共包括4個連結串列,主LRU、輔助LRU、主LRUW和輔助LRUW,前兩者是在buffer cache中尋找可以覆蓋的buffer塊,後兩者也是DBWR用於寫髒塊的。

物理讀時,資料塊要寫到buffer cache的哪個地方呢?覆蓋不常用的buffer ,LRU就登場了,LRU會將所有的buffer都連結在一起,主LRU分為冷端和熱端,每個buffer的訪問次數都有一個計數器TCH,3秒一個階段,每階段只要有程式訪問,其值就增加1。

一般輔助LRU佔總buffer數的75% ,主LRU輔助LRU主LRUW和輔助LRUW為 一個workset 由buffer cache lru chain latch保護。

物理讀的步驟:

1>獲取buffer cache lru chain latch的保護

2>先從輔助LRU連結串列的尾端搜尋可以覆蓋的buffer(不是髒塊,TCH小於2)

3>找到可以覆蓋的buffer之後,將其從輔助連結串列的尾端移到主LRU的冷端頭

4>釋放buffer cache chain lru  latch

輔助LRU為空的時候 會從主LRU尾去查詢buffer,這個過程中如果TCH>2的將會被移到熱鍛頭並且TCH清0,如果有髒塊也是不能被覆蓋的,會被移到LRUW連結串列中,被選中的buffer將會被移動到冷端頭,並讀入資料。

當然輔助LRUW不會一直為空的,SMON程式會每3秒醒來一次,申請獲得buffer cache chain lru latch,然後檢查主輔LRU的長度,如果輔助LRU小於25%,SMON將會從主LRU的冷端尾搜尋TCH<2的費髒塊,將其移動到輔助LRU中。

X$kcbwds中可以檢視主輔LRU的情況。

大表和小表是由small_table_threshold的隱藏引數控制的,該值預設為buffer cache數的2%

如果是大表,全表掃描oracle會額外處理,物理讀的塊不會進去主LRU,只會使用輔助LRU的空間,塊的TCH=0,11gR2之後,將自動使用直接路徑讀,不再進入buffer cache。

髒連結串列LRUW

TCH<2的髒塊,這些髒塊會被移動到LRUW中,對於比較熱的髒塊,不急於寫。當髒塊被移動到LRUW中,並不會馬上被寫磁碟,DBWR程式會每3秒鐘醒來一次,會將髒塊移動到輔助LRUW中,從輔助LRUW中寫磁碟。這時候就是個有一個髒塊就會寫,而不是等到一定的數量之後再寫。

Buffer  busy wait

前面提到過 buffer busy wait 是服務程式在掃描了40%(受隱含引數db_block_max_scan_pct控制)的LRU之後還沒有找到可以覆蓋的buffer(被pin住的,髒塊。TCH>=2的都不允許被覆蓋 ),程式休眠,直到找到可以覆蓋的buffer為止。當進入下一流程,會首先判斷buffer中的的髒塊數,總髒塊數超過buffer的25%(這個值由隱含引數db_large_dirty_queue:Number of buffers which force dirty queue to be write控制),將不會等待3秒超時了,而是直接喚醒DBWR寫髒塊。

DBWR被喚醒後,會首先檢查LRUW,如果有髒塊,則馬上開始寫,如果沒有髒塊,則開始檢查檢查點佇列,判斷是否需要從檢查點佇列寫髒塊,

從檢查點佇列寫髒塊是採用的增量檢查點的方式,從LRUW寫髒塊是採用的,是對增量檢查點的一點補充。伺服器程式掃描LRU時遇到髒塊如果不移動到LRUW,會增加LRU掃描時間,這樣會導致LRU latch競爭。

v$sysstat :physical write from cache,DBWR從buffer cache中寫入磁碟的髒塊,DBWR checkpoint buffer write指的是從檢查點佇列中寫出的所有髒塊數,兩者意見,就是DBWR從LRUW中寫磁碟的髒塊數。

髒塊一旦進入 LRUW則有以下兩種情況,會被寫出:

檢查點佇列中的髒buffer沒有達到總buffer數的25%,那麼等待3秒超時,DBWR會從LRUW中寫髒塊。

檢查點佇列中的髒buffer達到總buffer數的25%,不需要等待超時,伺服器程式直接喚醒DBWR,醒來後的DBWR馬上會從LRUW中寫髒塊。

 日誌切換:

日誌切換隻是喚醒DBWR 並告知DBWR已經發生了日誌切換。日誌切換還會觸發CKPT程式寫資料檔案頭,當日志檔案狀態由ACTIVE變為INACTIVE的時候,CKPT才會去寫檔案頭。

日誌切換時,CKPT會找到redo file在檢查點佇列中的RBA最大的髒塊,將他的SCN RBA通知DBWR

然後CKPT每3秒醒來的時候,發現redo file的髒塊還沒有完全寫完,再一次醒來,全部寫完之後會:修改控制檔案中的redo file 的狀態,新狀態為inactive ,修改控制檔案中的SCN,修改資料檔案頭的SCN和RBA ,總結一下就是,日誌切換時,LGWR通知CKPT和DBWR,然後馬上開始向下一組redo file中寫redo recorder。

 切換期間 多有的DML DDL都會被阻塞,程式在等待切換的過程中可能會有 logfile switch 等待。DBWR接到LGWR通知後馬上醒來,按正常工作流程工作,CKPT也會馬上醒來,檢查DBWR的寫進位制,確定是否現在的current redo file的髒塊都寫入磁碟了,都寫了,會馬上修改日誌檔案狀態、資料檔案相關狀態。日誌切換並不是通知DBWR寫髒塊,而是通知它發生了日誌切換,所以DBWR會醒來按原流程寫髒塊。

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

相關文章