InnoDB Buffer Pool詳解(緩衝池) 什麼是Buffer Pool? Buffer Pool的內存結構 Buffer Pool處理流程 配置 寫數據 change buffer

什麼是Buffer Pool?

Buffer Pool是MySQL InnoDB引擎用於緩存訪問到的表數據的一塊內存空間,主要用於加速SQL的執行速度,因爲內存的處理速度要遠高於訪問磁盤。說白了,其實它就相當於我們項目中的Redis緩存,直接訪問數據庫太慢了,使用Redis做一層緩衝;同理,直接從磁盤獲取數據太慢了,使用Buffer Pool做一層緩衝

Buffer Pool的內存結構

我們來看下Buffer Pool的內存結構



可以看出,Buffer Pool由1個大鏈表組成。爲什麼用鏈表來組織數據呢?因爲Buffer Pool既然爲緩存,肯定有對應的數據淘汰策略,不可能將所有的數據都拿到內存中存儲,常見的緩存策略有LRU、LFU等,都是基於鏈表實現,Buffer Pool採用了基於LRU的自定義淘汰策略,用於解決標準LRU策略中的一些問題。
Buffer Pool鏈表一分爲二爲new sublist與old sublist,兩個鏈表首尾相連。默認情況下,old list佔用總鏈表3/8,裏面存儲的是最近很少訪問的數據,即將要淘汰的數據;剩下的爲new list,裏面存儲的是最近才被訪問的數據。

Buffer Pool處理流程

我們來看下Buffer Pool是如何利用這兩個鏈表實現內存管理的。

當數據被讀取的時候會存入Buffer Pool,這裏的讀取包含兩個操作,一個是用戶觸發的讀取,例如SQL query;或者是InnoDB自動觸發的預讀讀取。

什麼是預讀?用於異步將磁盤的頁InnoDB數據以page爲單位存儲)讀取到buffer pool中,預料這些頁會馬上被讀取到page(數據的,因爲InnoDB猜測這些數據可能很快就會被用到。他會帶來extent(默認64個page組成一個extent)中的所有page。有兩種預讀算法:

  • 線性預讀【預測在buffer pool中被訪問到的數據它臨近的頁也會很快被訪問到,可以使用innodb_read_ahead_threashold配置設置當連續讀到多少個page時觸發一次預讀】
  • 隨機預讀【根據已經在buffer pool中存在的page來猜測哪些數據將會被讀取,如果隨機預讀開啓,InnoDB如果發現Buffer Pool中有13個來自一個extent的page,那麼將會發起異步請求讀取該extent剩餘的page】

被讀取的page將會被插入old list的頭部,讀取old list中的page會使其變“young”,會將其移動到new list的頭部。如果page由於用戶行爲被讀取,page第一次被訪問的時候就會使其變“young”。這樣隨着page不斷被訪問,new list數據越來越多,超過限制後就會存入old list中,若old list也滿了之後,就會從old list的尾部進行page的驅逐。
採用old list與new list這樣的結構可以有效避免預讀的數據不被訪問的情況,如果只是原始的LRU算法,那麼預讀的數據也會被加入到鏈表的頭部,會把真正的熱數據往下“擠”,而假設預讀的數據又不會被訪問,那麼Buffer Pool中會存儲大量的冷數據,失去了做緩存的作用。

Buffer Pool如何解決大數據量讀取的情況?
假設用戶執行了一條全表查詢的SQL,恰好這個表數據又很大,這就導致Buffer Pool中大量熱數據被這個全表查詢所替換,而這個數據可能就只會被快速的再訪問幾次,之後就不再被訪問了。
使用innodb_old_blocks_time配置一個時間窗口參數,在第一次訪問該頁面之後,如果在該窗口時間內訪問該page,該page也不會移動到new list的頭部了

配置

size必須是innodb_buffer_pool_chunk_size*innodb_buffer_pool_instances的倍數
將buffer pool拆分成多個instance可以提高併發度,每個instance都可以看做一個小的buffer pool,這樣可以減少不同線程讀寫緩存的鎖衝突

寫數據

Free鏈表:雙向鏈表,記錄那些緩衝頁是空閒的
Flush鏈表:管理Buffer Pool中的髒頁,後臺線程定時刷髒

change buffer

對於寫請求,若修改數據在緩衝池中,直接修改緩衝池數據之後寫入磁盤即可。
若修改數據沒在緩衝池中,需要先將數據讀取到緩衝池,修改數據,寫入磁盤,需要讀取磁盤數據。


buffer pool的一部分,當我們修改了不在buffer pool中的二級非唯一索引數據(若是唯一索引,innodb必須讀取磁盤做唯一性檢查),會將修改的內容先緩存到change buffer中,等未來數據被讀取時,再將數據合併(merge)恢復到緩衝池中的技術,change buffer主要用於緩存insert ,update, delete語句的結果。寫緩衝的目的是降低寫操作的磁盤IO,提升數據庫性能。

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