你知道MySQL的LRU鏈表嗎?
相信大家對LRU鏈表是不陌生的,算是一種基礎的數據結構!
LRU:Least Recently Used
一、簡述傳統的LRU鏈表
LRU:Least Recently Used
相信大家對LRU鏈表是不陌生的,它算是一種基礎的數據結構吧,而且想必面試時也被問到過什麼是LRU鏈表,甚至是讓你手寫一個LRU鏈表。
如果你讀了上一篇:你有沒有搞混查詢緩存和BufferPool?談談看!
想必你已經知道了MySQL的Buffer Pool機制以及MySQL組織數據的最小單位是數據頁。並且你也知道了 數據頁在Buffer Pool中是以LRU鏈表的數據結構組織在一起的。
其實所謂的LRU鏈表本質上就是一個雙向循環鏈表,如下圖:
下面我們結合LRU鏈表和數據頁機制描述一下MySQL加載數據的機制:
我們將從磁盤中讀取的數據頁稱為young page,young page會被直接放在鏈表的頭部。已經存在於LRU鏈表中數據頁如果被使用到了,那麼該數據頁也被認為是young page而被移動到鏈表頭部。這樣鏈表尾部的數據就是最近最少使用的數據了,當Buffer Pool容量不足,或者後台線程主動刷新數據頁時,就會優先刷新鏈表尾部的數據頁。
二、傳統LRU鏈表的不足
相信你之前肯定聽說過操作系統級別的空間局部性原理:
spatial locality(空間局部性):也就是說讀取一個數據,在它周圍內存地址存儲的數據也很有可能被讀取到,於是操作系統會幫你預讀一部分數據。
MySQL也是存在存在預讀機制的!
- 當Buffer Pool中存儲着一個區中13個連續的數據頁時,你再去這個區裏面讀取,MySQL就會將這個區裏面所有的數據頁都加載進Buffer Pool中的LRU鏈表中。(然後可能你根本不會使用這些被預讀的數據頁)
- 當你順序的訪問了一個區中大於
innndb_read_ahead_threshold=56
個數據頁時,MySQL會自動幫你將下一個相鄰區中的數據頁讀入LRU鏈表中。(這個機制默認是被關閉的) - 當你執行
select * from xxx;
時,如果表中的數據頁非常多,那這些數據頁就會一一將Buffer Pool中的經常使用的緩存頁擠下去,可能留在LRU鏈表中的全部是你不經常使用的數據。
綜上你可以看到,所謂的預讀機制的優勢,實際上違背了LRU去實現將最近最少使用的數據頁刷入磁盤的設計初衷。
三、MySQL的LRU鏈表
接下來我們看下MySQL的Buffer Pool是如何定製LRU鏈表的,已經LRU幫InnoDB解決了什麼問題。
當業務進行大量的CRUD時,需要不斷的將數據頁讀取到buffer pool中的LRU鏈表中。
MySQL的LRU鏈表長下面這樣。
LRU鏈表被MidPoint分成了New Sublist和Old Sublist兩部分。
其中New Sublist大概佔比5/8,Old Sublist佔比3/8。
New Sublist存儲着young page,而Old Sublist存儲着Old Page。
我們可以通過如下的方式查看MidPoint的默認值。
用戶可以根據自己的業務動態的調整這個參數!
這其實是一種冷熱數據分離設計思想。他相對於傳統的LRU鏈表有很大的優勢
四、MySQL定製LRU鏈表的優勢
而對於MySQLLRU鏈表來說,通過MidPoint將鏈表分成兩部分。
從磁盤中新讀出的數據會放在Old Sublist的頭部。這樣即使你真的使用select * from t;
也不會導致New Sublist中的經常被訪問的數據頁被刷入磁盤中。
正常情況下,訪問Old Sublist中的緩存頁,那麼該緩存頁會被提升到New Sublist中成為熱數據。
但是當你通過 select * from t
將一大批數據加載到Old Sublist時,然後在不到1s內你又訪問了它,那在這段時間內被訪問的緩存頁並不會被提升為熱數據。 這個1s由參數innodb_old_blocks_time
控制。
另外:New SubList也是經過優化的,如果你訪問的是New SubList的前1/4的數據,他是不會被移動到LRU鏈表頭部去的。
當然你可能對什麼是數據區並不了解,別急。白日夢將在第13篇文章中同你分享什麼是數據區
五、推薦閱讀
4、能談談year、date、datetime、time、timestamp的區別嗎?
參考:
//dev.mysql.com/doc/refman/5.7/en/innodb-buffer-pool.html
//dev.mysql.com/doc/refman/5.7/en/innodb-performance-midpoint_insertion.html
//dev.mysql.com/doc/refman/5.7/en/innodb-performance-read_ahead.html
關注送書!《Netty實戰》
文章公號號首發!連載中!關注微信公號回復:「抽獎」 可參加抽📖活動