buffer pool是一種減少磁盤io讀的機制,原理是將訪問過的磁盤數據暫留在內存中,這樣下次訪問相同的數據就不需要讀磁盤了。這個思想在平時的開發中,也經常用到,比如我們通常會在數據庫前加一層memcache以及redis的緩存,防止熱點數據。
mysql的內存緩存叫做buffer pool。緩存的單位是頁,頁是mysql管理磁盤的基本單位,也就是mysql每一次的磁盤io都是至少操作一個頁的數據量。
buffer pool使用一種特定的lru算法管理緩存頁。因爲mysql讀取磁盤有預讀機制,簡單來講就是,讀取一個頁,也會讀取相鄰的若干頁,因爲根據經驗,相鄰頁被使用的概率是比較高的。
由於有預讀機制,導致使用傳統的lru算法不合適。因爲,預讀的頁可能沒有被使用,所以不應該緩存。對於這些預讀失敗的頁,mysql有特殊的處理機制。
簡言之就是lru鏈表分爲兩部分:新生代及老生代。
新生代的尾部是老生代的開始。當一個頁從磁盤被讀入時,優先加入到老生代的鏈首,如果該頁被訪問到了,纔將其移到新生代的鏈首,否則就一直在老生代中,所以,預讀失敗的頁會優先被淘汰。
另外還有一個概念是"老生代停留時間窗口",新頁進入到老生代後,只有停留時間超過一個閾值T後,纔會被移到新生代,爲了防止掃表導致的無效數據。(具體機制不確定。。。)
參數:
1.innodb_buffer_pool_size:buffer pool大小,貌似是儘可能大?;
2.innodb_old_blocks_pct:老生代比例;
3.innodb_old_blocks_time:老生代停留時間閾值;