為什麼Oracle要搞出兩個髒連結串列

wei-xh發表於2018-08-23

為什麼Oracle要搞出兩個髒列表:一個Checkpoint Queue,一個LRUW。

兩個連結串列設計的目的是不一樣的。

Checkpoint Queue嚴格按照資料塊第一次被修改的時間排序,DBWR會沿著Checkpoint Queue寫髒資料,並將寫的位置記錄在控制檔案中,Oracle這麼做的目的是,將越早被修改的塊,越早被寫出,達到減少例項恢復時間的目的。在例項異常down後,只需要從控制檔案中讀取檢查點的位置,把這個點之後的重做日誌前滾就可以恢復例項。

而LRUW連結串列不是這個目的。這個問題,稍顯複雜,慢慢來說。

我們知道,一般情況下,buffer cache的記憶體是要比資料檔案小的多的,在例項執行一段時間後,buffer cache就會呈現出“滿”的狀態,在出現新的記憶體空間請求時候,就需要在buffer cache中犧牲掉一些記憶體塊來儲存新的資料。

那麼在空間不夠的情況下,哪些塊會被犧牲,刷出buffer cache呢?

一般是TCH小於2,CR塊,全表掃描的塊優先被犧牲重用。這些需要被重用的塊裡是可能包含髒塊的。 那麼這些髒塊不同於CR塊,不能直接被重用,需要被刷到磁碟

那麼,LRUW連結串列來了,把需要刷出的髒塊放到LRUW連結串列上,單獨設計這個連結串列的目的是,可以最大化寫出髒塊的效率。例如可以合併物理空間上連續的髒塊,減少IO數量。例如伺服器程式,掃描到髒塊後,把髒塊鏈到LRUW,就不用管其他事,可以繼續自己的工作。

此外,這裡補充一些細節資訊。

在系統急需大量空閒塊的時候,伺服器程式會搜尋LRU連結串列,如果發現了髒快且TCH小於2(因為是從LRU冷端掃起,所以髒快的TCH大機率會很小)那麼就挪到LRUW連結串列上,然後這些塊後續會從LRUW寫出到磁碟,最終這個記憶體就成了free的記憶體塊,就可以被挪到LRU-Aux上被重用了,另外這個塊被寫入磁碟後,需要從Checkpoint Queue摘除。

一個塊被修改變髒後,一定會進入到Checkpoint Queue佇列,但是不會立即進入到LRUW佇列,只有發生程式搜尋LRU連結串列的時候,發現該塊TCH數比較小,且沒有被pin住,才會被放入LRUW連結串列然後被寫出到磁碟。

很多人會認為,LRU連結串列裡的塊都應是乾淨的塊。其實LRU連結串列裡的髒快應該是比較多的,特別是如果這些髒塊訪問比較頻繁,那麼TCH數就會比較高,按照演算法就不會被放到LRUW連結串列裡,它會一直呆在LRU連表裡,當然這個髒塊最終會從Checkpoint Queue寫出變為乾淨的塊。

這裡還有一個有趣的知識點,很多人都存在誤解,這些塊從Checkpoint Queue寫出到磁碟後,其實 
1. 不會改變這個塊在LRU連結串列裡的位置 
2. 依然存在在記憶體裡,很多人有誤解,認為寫出髒快後,這個塊就不在記憶體裡了,其實並不是這樣的。是從LRUW連結串列裡寫出的髒塊才會被刷出記憶體。


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

相關文章