MySQL的Flush-List和臟頁的落盤機制
一、回顧
MySQL啟動后Buffer Pool會初始化。Buffer Pool也會初始化好N多個空白的緩存頁,以及它們的描述數(shù)據(jù)會被組織成LRU鏈表以及FreeList 雙向鏈表。
這時你從磁盤中讀取一個數(shù)據(jù)頁,會先從Free List中找出一個空閑緩存頁的描述信息,然后將你讀出的數(shù)據(jù)頁中加載進緩存頁中。同時將緩存頁的描述信息從Free List中剔除,此外該描述信息塊還會被維護進LRU鏈表中。
數(shù)據(jù)頁被加載進Buffer Pool后你就可以對其進行變更操作了。
二、Flush List
為了加快響應(yīng)客戶端的速度,MySQL會在Buffer Pool中對數(shù)據(jù)進行修改,可是一旦你對LRU鏈表中的緩存頁做了修改,那該頁中的數(shù)據(jù)和磁盤中的數(shù)據(jù)頁信息就不一致了!大家一般管這種數(shù)據(jù)頁叫做臟頁。
為了保證數(shù)據(jù)的最終一致性,MySQL是需要將臟頁刷新回磁盤的!
但是問題是:需要將哪些數(shù)據(jù)頁刷新回磁盤呢?
這就引出了Flush List~
Flush List 和 Free List很像,都是由Buffer Pool中數(shù)據(jù)描述信息組織而成的雙向鏈表。
一旦你對內(nèi)存中的緩沖頁作出了修改,那該緩沖頁對應(yīng)的描述信息塊就會添加進 Flush List。這樣當Buffer Pool中的數(shù)據(jù)頁不夠用時,我們就可以優(yōu)先將 Flush List中的臟數(shù)據(jù)頁刷新進磁盤中。
如果你讀了前幾篇文章那你肯定知道了 LRUList、FreeList、FlushList、Buffer Pool、臟頁、臟數(shù)據(jù)。
下面乘勝追擊!一起看一下臟頁的落盤機制
三、什么是臟頁?什么是臟數(shù)據(jù)?
什么是臟頁?
我在介紹Flush List 的那篇文章有提及,臟頁就是LRU鏈表中被修改了的緩存頁。他們和磁盤中的數(shù)據(jù)頁不一致,臟頁是需要被刷新回磁盤的。
什么是臟數(shù)據(jù)?
這個問題其實引出了臟讀的概念。舉個例子:事物A中讀取到了事物B中未提交的數(shù)據(jù),我們管這些數(shù)據(jù)叫做臟數(shù)據(jù)。
四、臟頁刷回磁盤的時機
當Buffer Pool不夠用時,根據(jù)LRU機制,MySQL會將Old SubList部分的緩存頁移出LRU鏈表。如果被移除出去的緩存頁的描述信息在Flush List中,MySQL就得將其刷新回磁盤。
InnoDB存儲引擎將臟頁刷回磁盤的時機有蠻多的,你可以把它當作拓展知識大概瀏覽一下。
1、當MySQL數(shù)據(jù)庫關(guān)閉時,會將所有的臟數(shù)據(jù)頁刷新回磁盤。這個功能由參數(shù):innodb_fast_shutdown=0控制,默認讓InnoDB在關(guān)閉前將臟頁刷回磁盤,以及清理掉undo log。
2、有一個后臺線程Master Thread會按照每秒或者每十秒的速度,異步的將Buffer Pool中一定比例的頁面刷新回磁盤中。
3、在MySQL5.7中,Buffer Pool的刷新由page cleaner threads完成。
我們可以通過innodb_page_cleaners參數(shù)控制page cleaner threads線程的數(shù)量,但是當你將這個數(shù)值調(diào)整的比Buffer Pool的數(shù)量還大時,MySQL會自動將 innodb_page_cleaners數(shù)量設(shè)置為innodb_buffer_pool_instances的數(shù)量。
Innodb1.1.x之前需要保證LRU列表中有至少100個空閑頁可以使用。低于這個閾值就會觸發(fā)臟頁的刷新。
從MySQL5.6,也就是innodb1.2.X開始,innodb_lru_scan_depth參數(shù)為每個緩沖池實例指定page cleaner threads 掃描Buffer Pool來查找要刷新的臟頁的下行距離。默認為1024,該后臺線程每秒都會執(zhí)行一次。
4、當臟數(shù)據(jù)頁太多時,也會觸發(fā)將臟數(shù)據(jù)頁刷新回磁盤。該機制可由參數(shù)innodb_nax_dirty_pages_pct控制,比如將其設(shè)置為75,表示,當Buffer Pool中的臟數(shù)據(jù)頁達到整體緩存的75%時,觸發(fā)刷新的動作。現(xiàn)實情況是該參數(shù)默認值為0。以此來禁用Buffer Pool早期的刷新行為。
5、當redo log不可用時,也會強制臟頁列表中的臟頁刷新回磁盤。這個機制同樣由一個后臺線程完成。
五、其他關(guān)于臟頁刷新的知識點
刷新臨接數(shù)據(jù)頁:意思是當MySQL將某臟頁刷新回磁盤時,是否也以相同的態(tài)度將該臟頁鄰接的臟頁一并刷新回磁盤。
可以通過參數(shù)innodb_flush_neighbors控制該過程。
- 設(shè)置為0時表示,禁用刷新鄰接的功能。
- 設(shè)置為1時表示,以相同的態(tài)度刷新其鄰接的臟頁。
- 設(shè)置為2時表示,以相同的程度刷新臟頁。
那如何選擇將其設(shè)置為哪種狀態(tài)呢?
你可以根據(jù)MySQL實例所在機器的存儲類型來決定。如果為HDD存儲建議將其開啟,因為HDD的磁盤刷新速率較低,開啟該參數(shù)后可以有效的減少IO操作。相反如果使用SSD存儲,其本身就有高磁盤IO的特性,建議禁用該參數(shù)。
以上就是MySQL的Flush-List和臟頁的落盤機制的詳細內(nèi)容,更多關(guān)于MySQL Flush-List和臟頁的落盤機制的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MySQL通過DQL實現(xiàn)對數(shù)據(jù)庫數(shù)據(jù)的基本查詢
這篇文章給大家介紹了MySQL如何通過DQL進行數(shù)據(jù)庫數(shù)據(jù)的基本查詢,文中通過代碼示例和圖文結(jié)合介紹的非常詳細,對大家的學習或工作有一定的幫助,需要的朋友可以參考下2024-01-01解析:內(nèi)聯(lián),左外聯(lián),右外聯(lián),全連接,交叉連接的區(qū)別
本篇文章是對內(nèi)聯(lián),左外聯(lián),右外聯(lián),全連接,交叉連接的區(qū)別進行了詳細的分析介紹,需要的朋友參考下2013-07-07MySQL表LEFT JOIN左連接與RIGHT JOIN右連接的實例教程
這篇文章主要介紹了MySQL表LEFT JOIN左連接與RIGHT JOIN右連接的實例教程,表連接操作是MySQL入門學習中的基礎(chǔ)知識,需要的朋友可以參考下2015-12-12mysql觸發(fā)器之創(chuàng)建使用觸發(fā)器簡單示例
這篇文章主要介紹了mysql觸發(fā)器之創(chuàng)建使用觸發(fā)器,結(jié)合實例形式分析了mysql創(chuàng)建、查看、調(diào)用觸發(fā)器的相關(guān)操作技巧,需要的朋友可以參考下2019-12-12Spring jdbc中數(shù)據(jù)庫操作對象化模型的實例詳解
這篇文章主要介紹了Spring jdbc中數(shù)據(jù)庫操作對象化模型的實例詳解的相關(guān)資料,希望通過本文大家能夠了解掌握這部分內(nèi)容,需要的朋友可以參考下2017-09-09