MySQL —— 緩衝池 Buffer Pool

本文主要內容源自官網:https://dev.mysql.com/doc/refman/8.0/en/innodb-buffer-pool.html

感興趣的可以直接閱讀

緩衝池是主內存的一塊區域,在 InnoDB 訪問表和索引數據時會在其中進行高速緩存(可以聯繫 CPU 的高速緩存)。在專用服務器上,通常會把 80% 的內存分配給緩衝池。

緩衝池被分爲多個頁面,這些頁面可能包含多個行。緩衝池使用列表數據結構。使用 LRU (Least Recently Used,最近最少使用)算法的變體將數據從緩存中老化。

緩衝池 LRU 算法

緩衝池 LRU 算法將緩衝池作爲列表進行管理。當緩衝池空間不足,但有新頁面需要添加到緩衝池時,將驅逐最近最少使用的頁面,並將新頁面添加到列表的 Midpoint(中點)。總列表分爲兩個子列表(Sublist):

1. 最前面的是最近訪問過的新頁面(或者叫 young 頁面,年輕頁面)子列表

2. 末尾是最近訪問的舊頁面的子列表

 

該算法將經常需要訪問的頁面保留在 New Sublist。Old Sublist 包含不常用的頁面,這些頁面是驅逐的候選對象。

通常情況,該算法遵循以下規則:

1. \frac{3}{8} 的 Buffer Pool 用於 Old Sublist

2. 列表的 Midpoint 是 New Sublist 的 Tail 和 Old Sublist 的 Head 相交的邊界。

3. 當 InnoDB 將頁面讀入緩衝池時,它首先將頁面插入 Midpoint。通過用戶觸發的動作(比如 SQL 查詢)或者預讀操作可以對頁面進行讀取。

注意:官方這裏說的讀取(read)並不代表訪問(access),請看下面。

4. 訪問(access)Old Sublist 中的頁面會讓其變得 young,然後將其移至 New Sublist 的 Head。如果是因爲用戶觸發的動作需要讀取頁面,則將立即進行第一次 access,使頁面 young。如果使由於預讀操作而讀取了該頁面,則第一次 access 不會立即訪問,甚至在頁面離開之前都不會發生

注意:預讀未必會讓頁面變 young。

5. 隨着數據庫的運行,通過將頁面移動到列表的尾部,緩衝池中的頁面將會“老化”。New 和 Old Sublist 都會隨着其他頁面的更新而老化。隨着將頁面插入 Midpoint,舊子列表中的頁面也會老化。最終,未使用的頁面到達子列表的尾部並被逐出。

注意:這裏有個有趣的現象,頁面是先插入到 Midpoint,而且這些頁面插入之後屬於 Old Sublist 的範圍,所以他們很可能會馬上“老化”,唯一讓他們變得 young 的途徑就是 access 一次。

 

默認情況下,查詢(Query)讀取的頁面會立即移入新的子列表,這意味着它們在緩衝池停留的時間更長。

舉個例子,mysqldump 操作或者 SELECT 不帶 WHERE 子句的語句可能會將大量數據帶入緩衝池,並驅逐出相當多的舊數據,即使加入 New Sublist Head 的新數據可能都不會再被使用了。同樣,預讀線程加載的頁面,且僅僅訪問過一次,那麼也會移至 New Sublist 的開頭。這些情況可能會將常用頁面推到舊的子列表,然後被逐出。

所以,這似乎有個問題,有些頁面命名使用的頻率不如其他頁面,卻可以插在其他頁面前面,甚至逐出其他頁面 ,官方給出了優化此行爲的方法:讓緩衝池的掃描具有“抵抗力”配置 InnoDB 緩衝池預讀(具體見官網)。

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章