14 當我們更新Buffer Pool中的數(shù)據(jù)時,flush鏈表有什么用?

當我們更新Buffer Pool中的數(shù)據(jù)時,flush鏈表有什么用?
1、昨日思考題解答
我們先解答一下昨日的思考題,昨天是問了大家一個問題,Buffer Pool中會不會有內(nèi)存碎片?
答案是:當然有
因為Buffer Pool大小是你自己定的,很可能Buffer Pool劃分完全部的緩存頁和描述數(shù)據(jù)塊之后,還剩一點點的內(nèi)存,這一點點的內(nèi)存放不下任何一個緩存頁了,所以這點內(nèi)存就只能放著不能用,這就是內(nèi)存碎片。
那怎么減少內(nèi)存碎片呢?
其實也很簡單,數(shù)據(jù)庫在Buffer Pool中劃分緩存頁的時候,會讓所有的緩存頁和描述數(shù)據(jù)塊都緊密的挨在一起,這樣盡可能減少內(nèi)存浪費,就可以盡可能的減少內(nèi)存碎片的產(chǎn)生了。
如果你的Buffer Pool里的緩存頁是東一塊西一塊,那么必然導致緩存頁的內(nèi)存之間有很多內(nèi)存空隙,這就會有大量的內(nèi)存碎片了。
2、臟數(shù)據(jù)頁到底為什么會臟?
接著我們看一個很關(guān)鍵的問題,你在執(zhí)行增刪改的時候,如果發(fā)現(xiàn)數(shù)據(jù)頁沒緩存,那么必然會基于free鏈表找到一個空閑的緩存頁,然后讀取到緩存頁里去,但是如果已經(jīng)緩存了,那么下一次就必然會直接使用緩存頁。
反正不管怎么樣,你要更新的數(shù)據(jù)頁都會在Buffer Pool的緩存頁里,供你在內(nèi)存中直接執(zhí)行增刪改的操作。
接著你肯定會去更新Buffer Pool的緩存頁中的數(shù)據(jù),此時一旦你更新了緩存頁中的數(shù)據(jù),那么緩存頁里的數(shù)據(jù)和磁盤上的數(shù)據(jù)頁里的數(shù)據(jù),是不是就不一致了?
這個時候,我們就說緩存頁是臟數(shù)據(jù),臟頁
? ? ? ? ? ?

? ? ? ? ? ? ?
3、哪些緩存頁是臟頁呢?
其實通過之前的學習,我們都是知道一點的,最終這些在內(nèi)存里更新的臟頁的數(shù)據(jù),都是要被刷新回磁盤文件的。
但是這里就有一個問題了,不可能所有的緩存頁都刷回磁盤的,因為有的緩存頁可能是因為查詢的時候被讀取到Buffer Pool里去的,可能根本沒修改過!
所以數(shù)據(jù)庫在這里引入了另外一個跟free鏈表類似的flush鏈表,這個flush鏈表本質(zhì)也是通過緩存頁的描述數(shù)據(jù)塊中的兩個指針,讓被修改過的緩存頁的描述數(shù)據(jù)塊,組成一個雙向鏈表。
凡是被修改過的緩存頁,都會把他的描述數(shù)據(jù)塊加入到flush鏈表中去,flush的意思就是這些都是臟頁,后續(xù)都是要flush刷新到磁盤上去的
所以flush鏈表的結(jié)構(gòu)如下圖所示,跟free鏈表幾乎是一樣的。
? ? ? ? ? ?

? ? ? ? ? ? ?
4、flush鏈表構(gòu)造的偽代碼演示
我們用一些偽代碼來給大家展示一下這個flush鏈表的構(gòu)造過程,比如現(xiàn)在緩存頁01被修改了數(shù)據(jù),那么他就是臟頁了,此時就必須把他加入到flush鏈表中去
此時緩存頁01的描述數(shù)據(jù)塊假設如下所示

好了,我們可以看到,現(xiàn)在flush鏈表的基礎(chǔ)節(jié)點就指向了一個block01的節(jié)點,接著比如緩存頁02被更新了,他也是臟頁了,此時他的描述數(shù)據(jù)塊也要被加入到flush鏈表中去
此時偽代碼如下:

大家可以看到,當你更新緩存頁的時候,通過變換緩存頁中的描述數(shù)據(jù)塊的flush鏈表的指針,就可以把臟頁的描述數(shù)據(jù)塊組成一個雙向鏈表,也就是flush鏈表,而且flush鏈表的基礎(chǔ)節(jié)點會指向起始節(jié)點和尾巴節(jié)點。
通過這個flush鏈表,就可以記錄下來哪些緩存頁是臟頁了!
End
專欄版權(quán)歸公眾號儒猿技術(shù)窩所有
未經(jīng)許可不得傳播,如有侵權(quán)將追究法律責任