buffer cache基本知識點

myownstars發表於2014-02-14
 

資料結構及Latch

buffer cache基本知識點



 

Oracle維護1個雜湊表,由一系列bucket組成,資料塊按照RDBA被對映至相應bucket;同一bucket下的資料塊形成一條連結串列,存放相同RDBA或雜湊衝突的資料塊;
通過雜湊表程式可快速定位一個資料塊的位置,其有cache buffer chain latch保護;


資料塊在buffer中有其生命週期,oracle採用least-recent-used + touch point演算法,故每個資料塊都位於LRU或LRUW連結串列中,為了提高效率每個連結串列各有一個輔助連結串列;
一組LRU & LRUW形成一個工作集,由cache buffer LRU chain latch保護;
資料庫剛啟動或執行flush buffer_cache時,所有記憶體塊都存於LRU-AUX中,初次訪問時放入LRU冷端頭(全表掃描例外);
塊修改後狀態變為dirty從而移入LRUW,進而放入LRUW-AUX並寫入磁碟;


8i引入增量檢查點,相應的新增了CKPTQ(類似的還有FILEQ/OBJQ),髒塊按LRBA順序插入CKPTQ,增量檢查點按順序讀取髒塊並將其寫入磁碟;
相應latch為checkpoint queue latch;


1個工作集包含如下queue

buffer cache基本知識點


常見問題

1

全表掃描與LRU-AUX
全表掃描的塊通常只位於LRU-AUX以便快速重用(除非指定cache選項),因此重複全表掃描某個表可能無法降低物理讀;可參照 http://www.laoxiong.net/table_scan_and_buffer_cache.html
oracle儘量按80:20的比例分配LRU/LRU-AUX,由此可能會產生詭異現象,譬如上面連結的最後評論所遇到的問題,vage在http://www.mythdata.com/post/8.html 進行了很好的闡釋:
當所有塊都在輔助LRU時,Oracle為了急於保證主、輔LRU,塊數量80%,20%的比例,第一次查詢時,會將大量的塊移到主LRU;
重新整理buffer_cache後,第一次查詢會把大部分塊會被放入LRU以滿足80:20比例(即便全表掃描也是如此),滿足此條件後後續的全表掃描則放入LRU-AUX;
注:11R2演算法有所改動,即第一次查詢若是全表掃描則buffer塊依然留在LRU-AUX中;

 

2
前臺程式如何搜尋free buffer?
Buffer cache分為多個工作集以round-robin方式儲存資料塊,前臺程式依次訪問每個工作集直至獲取cache buffer LRU chain latch,若LRU-AUX沒有足夠空閒塊則從LRU冷端頭遍歷;
若掃描一定的depth仍沒有足夠空閒塊,則通知DBWR寫髒塊並進行free buffer wait等待;

 

3
塊何時進入CKPTQ和LRUW?
變為髒塊後進入CKPTQ,需用到checkpoint queue latch;
對於後者,有3種可能
a DBWR每3秒喚醒一次,有兩個任務:
1)      檢查CKPTQ長度,若恢復時間可能超過fast_start_mttr_target則沿著CKPTQ寫髒塊
2)      檢查LRUW,有髒塊即寫
b 前臺程式掃描LRU時將遇到的髒塊放入LRUW
c  前臺程式掃描LRU depth時仍未發現可用塊,則喚醒DBWR將髒塊從CKTPQ移到LRUW,期間進行free buffer waits等待

 


4
如何寫髒塊?
有兩種方式:通過CKPTQ或LRUW,髒塊可同時位於CKPTQ和LRUW中;
前者並不改動塊在LRU中的位置,寫完磁碟後從CKPTQ中移除;
後者先將髒塊移入LRUW-AUX進行IO合併,寫到磁碟後將其放入LRU-AUX,可立即被重用,故free buffer waits等待時DBWR會從LRUW寫髒塊;

 

5
如何獲取current buffer?
a 找到RDBA對應的bucket,申請cache buffer chain latch遍歷其hash chain,跳過RDBA不匹配以及CR buffer
b 定位到CUR buffer,
1)      若請求S而buffer正在以X模式被佔用,則加入waiter list釋放cbc latch,並進行buffer busy waits等待
2)      請求X而buffer以S模式被佔用,則新建1個CUR buffer
不論有沒有成功pin住CUR buffer,都要及時釋放cache buffer chain latch
c 若此時塊不在記憶體,則以X模式pin住buffer header並釋放cbc latch,繼而從磁碟讀;若此時其他會話訪問該塊則會進行read by other session等待

 

6
如何判斷buffer塊位於哪個list?
SQL> select LRU_FLAG,count(*) from x$bh group by LRU_FLAG order by 2;
  LRU_FLAG   COUNT(*)
---------- ----------
         2        768
         4      83190
         6     244729
         0     327358
         8     655972
6/4 –LRU-AUX
0/2—LRU-cold
8/9—LRU-hot
LRU_FLAG為6、4,說明BUffer在輔助LRU中。為0、2,說明在主LRU的冷端,為8、9的,說明在主LRU的熱端。

 

參考資料
DSI 405
http://www.mythdata.com/post/8.html

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

相關文章