緩衝池是主記憶體中的一個區域,InnoDB
會在存取時快取資料表和索引資料。緩衝池允許直接從記憶體存取常用資料,從而加快處理速度。在專用伺服器上,通常會將高達 80% 的實體記憶體分配給緩衝池。
為了提高大量讀取操作的效率,緩衝池被分成頁面,這些頁面可能會包含多列。為了提高快取管理效率,緩衝池以頁面連結清單的形式實作;很少使用的資料會使用最近最少使用 (LRU) 演算法的變體從快取中清除。
瞭解如何利用緩衝池將常用資料保留在記憶體中是 MySQL 調整的重要方面。
緩衝池使用 LRU 演算法的變體作為清單來管理。當需要空間將新頁面新增至緩衝池時,會逐出最近最少使用的頁面,並將新頁面新增至清單的中間。這種中點插入策略會將清單視為兩個子清單
在開頭,最近存取的新(「年輕」)頁面的子清單
在結尾,最近較少存取到的舊頁面子清單
此演算法會將常用頁面保留在新的子清單中。舊的子清單包含較少使用的頁面;這些頁面是逐出的候選項目。
依預設,演算法的運作方式如下
緩衝池的 3/8 用於舊的子清單。
清單的中點是新的子清單的結尾與舊的子清單的開頭的界限。
當
InnoDB
將頁面讀取到緩衝池時,它最初會將其插入到中點 (舊的子清單的開頭)。讀取頁面可能是因為使用者起始操作 (例如 SQL 查詢) 所需,或是作為InnoDB
自動執行的預讀操作的一部分。存取舊子列表中的頁面會使其「「變年輕」」,並將其移動到新子列表的頭部。如果該頁面是因為使用者啟動的操作而需要讀取,則第一次存取會立即發生,並且該頁面會變年輕。如果該頁面是因為預讀操作而讀取,則第一次存取不會立即發生,並且可能在頁面被逐出之前都不會發生。
隨著資料庫的運作,緩衝池中未被存取的頁面會透過向列表尾部移動而「「老化」」。新舊子列表中的頁面都會隨著其他頁面變新而老化。舊子列表中的頁面也會隨著頁面插入到中點而老化。最終,未使用的頁面會到達舊子列表的尾部並被逐出。
預設情況下,查詢讀取的頁面會立即移動到新子列表中,這表示它們會在緩衝池中停留更久。例如,為 mysqldump 操作或沒有 WHERE
子句的 SELECT
陳述式執行的資料表掃描,可能會將大量資料帶入緩衝池,並逐出等量的舊資料,即使新資料永遠不會再次使用。同樣地,由預讀背景執行緒載入且僅存取一次的頁面也會移動到新列表的頭部。這些情況可能會將頻繁使用的頁面推到舊子列表中,使它們容易被逐出。有關優化此行為的資訊,請參閱第 17.8.3.3 節「使緩衝池具有掃描抵抗能力」,以及第 17.8.3.4 節「配置 InnoDB 緩衝池預取 (預讀)」。
InnoDB
標準監視器輸出在 BUFFER POOL AND MEMORY
區段中包含幾個關於緩衝池 LRU 演算法運作的欄位。有關詳細資訊,請參閱使用 InnoDB 標準監視器監控緩衝池。
您可以配置緩衝池的各個方面以提高效能。
理想情況下,您應將緩衝池的大小設定為實際可行的最大值,同時為伺服器上的其他程序保留足夠的記憶體,使其不會過度分頁。緩衝池越大,
InnoDB
的行為就越像記憶體資料庫,從磁碟讀取資料一次,然後在後續讀取期間從記憶體存取資料。請參閱第 17.8.3.1 節「配置 InnoDB 緩衝池大小」。在具有足夠記憶體的 64 位元系統上,您可以將緩衝池分成多個部分,以最大程度地減少並行操作之間對記憶體結構的爭用。有關詳細資訊,請參閱第 17.8.3.2 節「配置多個緩衝池實例」。
您可以將頻繁存取的資料保留在記憶體中,而無論來自將大量不常存取的資料帶入緩衝池的操作的突然活動高峰。有關詳細資訊,請參閱第 17.8.3.3 節「使緩衝池具有掃描抵抗能力」。
您可以控制如何以及何時執行預讀請求,以非同步方式將頁面預取到緩衝池中,以預期即將需要它們。有關詳細資訊,請參閱第 17.8.3.4 節「配置 InnoDB 緩衝池預取 (預讀)」。
您可以控制何時發生背景刷新,以及刷新速率是否根據工作負載動態調整。有關詳細資訊,請參閱第 17.8.3.5 節「配置緩衝池刷新」。
您可以配置
InnoDB
如何保留目前的緩衝池狀態,以避免在伺服器重新啟動後出現長時間的預熱期。有關詳細資訊,請參閱第 17.8.3.6 節「儲存和還原緩衝池狀態」。
InnoDB
標準監視器輸出 (可以使用 SHOW ENGINE INNODB STATUS
存取) 提供關於緩衝池運作的指標。緩衝池指標位於 InnoDB
標準監視器輸出的 BUFFER POOL AND MEMORY
區段中
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 2198863872
Dictionary memory allocated 776332
Buffer pool size 131072
Free buffers 124908
Database pages 5720
Old database pages 2071
Modified db pages 910
Pending reads 0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 4, not young 0
0.10 youngs/s, 0.00 non-youngs/s
Pages read 197, created 5523, written 5060
0.00 reads/s, 190.89 creates/s, 244.94 writes/s
Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not
0 / 1000
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read
ahead 0.00/s
LRU len: 5720, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
下表說明 InnoDB
標準監視器報告的緩衝池指標。
InnoDB
標準監視器輸出中提供的每秒平均值是根據上次列印 InnoDB
標準監視器輸出以來經過的時間計算的。
表 17.2:InnoDB 緩衝池指標
名稱 | 描述 |
---|---|
配置的總記憶體 | 為緩衝池配置的總記憶體 (以位元組為單位)。 |
配置的字典記憶體 | 為 InnoDB 資料字典配置的總記憶體 (以位元組為單位)。 |
緩衝池大小 | 配置給緩衝池的總大小 (以頁面為單位)。 |
可用緩衝區 | 緩衝池可用列表的總大小 (以頁面為單位)。 |
資料庫頁面 | 緩衝池 LRU 列表的總大小 (以頁面為單位)。 |
舊資料庫頁面 | 緩衝池舊 LRU 子列表的總大小 (以頁面為單位)。 |
已修改的資料庫頁面 | 緩衝池中目前已修改的頁面數目。 |
待處理讀取 | 正在等待讀取到緩衝池中的緩衝池頁面數目。 |
待處理寫入 LRU | 緩衝池內從 LRU 列表底部寫出的舊的髒頁數量。 |
待處理寫入刷新列表 | 在檢查點建立期間要刷新的緩衝池頁面數目。 |
待處理寫入單頁 | 緩衝池內待處理的獨立頁面寫入數目。 |
變年輕的頁面 | 緩衝池 LRU 列表中變年輕 (移動到「「新」」頁面子列表的頭部) 的頁面總數。 |
未變年輕的頁面 | 緩衝池 LRU 列表中未變年輕的頁面總數 (在「「舊」」子列表中停留且未變年輕的頁面)。 |
youngs/s | 緩衝池 LRU 列表中對舊頁面的存取,導致頁面變年輕的每秒平均值。如需詳細資訊,請參閱此表後的注意事項。 |
non-youngs/s | 緩衝池 LRU 列表中對舊頁面的存取,導致頁面未變年輕的每秒平均值。如需詳細資訊,請參閱此表後的注意事項。 |
讀取的頁面 | 從緩衝池讀取的頁面總數。 |
建立的頁面 | 在緩衝池內建立的頁面總數。 |
寫入的頁面 | 從緩衝池寫入的頁面總數。 |
reads/s | 每秒緩衝池頁面讀取的每秒平均數。 |
creates/s | 每秒建立的緩衝池頁面平均數。 |
writes/s | 每秒緩衝池頁面寫入的平均數。 |
緩衝池命中率 | 從緩衝池讀取相對於從磁碟儲存讀取的頁面的緩衝池頁面命中率。 |
young-making rate | 頁面存取導致頁面變年輕的平均命中率。如需詳細資訊,請參閱此表後的注意事項。 |
not (young-making rate) | 頁面存取未導致頁面變年輕的平均命中率。如需詳細資訊,請參閱此表後的注意事項。 |
預讀頁面 | 每秒平均預讀操作數。 |
未存取而被逐出的頁面 | 每秒平均未從緩衝池存取而被逐出的頁面數。 |
隨機預讀 | 每秒平均隨機預讀操作數。 |
LRU 長度 | 緩衝池 LRU 列表的總大小 (以頁面為單位)。 |
unzip_LRU 長度 | 緩衝池 unzip_LRU 列表的長度 (以頁面為單位)。 |
I/O 總和 | 已存取的緩衝池 LRU 列表頁面總數。 |
I/O 目前 | 目前間隔中存取的緩衝池 LRU 列表頁面總數。 |
I/O 解壓縮總和 | 已解壓縮的緩衝池 unzip_LRU 列表頁面總數。 |
I/O 解壓縮目前 | 目前間隔中已解壓縮的緩衝池 unzip_LRU 列表頁面總數。 |
注意事項:
youngs/s
指標僅適用於舊頁面。它是基於頁面存取次數。給定的頁面可能有多個存取,所有這些存取都會被計算。如果在沒有發生大型掃描時看到非常低的youngs/s
值,請考慮縮短延遲時間或增加用於舊子列表的緩衝池百分比。增加百分比會使舊子列表更大,以便該子列表中的頁面需要更長的時間才能移動到尾部,從而增加這些頁面再次被存取並變年輕的可能性。請參閱第 17.8.3.3 節「使緩衝池具有掃描抵抗能力」。non-youngs/s
指標僅適用於舊頁面。它基於頁面存取的次數。針對給定的頁面可能有多個存取,所有這些存取都會被計數。如果在執行大型資料表掃描時,沒有看到更高的non-youngs/s
值(以及更高的youngs/s
值),請增加延遲值。請參閱第 17.8.3.3 節,「使緩衝池能夠抵抗掃描」。young-making
速率會計算所有緩衝池頁面存取,而不僅僅是舊子列表中頁面的存取。young-making
速率和not
速率通常不會加總為整體緩衝池命中率。舊子列表中的頁面命中會導致頁面移動到新子列表,但新子列表中的頁面命中僅在它們與列表頭有一定距離時,才會導致頁面移動到列表頭。not (young-making rate)
是平均命中率,在此命中率下,由於未達到innodb_old_blocks_time
所定義的延遲,或由於新子列表中的頁面命中未導致頁面移動到列表頭,因此頁面存取沒有使頁面變年輕。此速率會計算所有緩衝池頁面存取,而不僅僅是舊子列表中頁面的存取。
緩衝池伺服器狀態變數和 INNODB_BUFFER_POOL_STATS
表格提供了許多與 InnoDB
標準監視器輸出中相同的緩衝池指標。如需更多資訊,請參閱範例 17.10,「查詢 INNODB_BUFFER_POOL_STATS 表格」。