一、free page:從未用過的頁sql
二、clean page:乾淨的頁,數據頁的數據和磁盤一致數據庫
三、dirty page:髒頁spa
SQL執行需求:日誌
一、找free頁code
二、刷新髒頁對象
一、這個頁不是熱的數據頁(刷冷頁)blog
二、這個頁最先修改時間(刷修改時間比較早的頁,有多是熱頁),方便日誌文件的覆蓋內存
三、覆蓋冷的clean頁
爲了實現上述需求,innodb用到鏈表技術(每種鏈表一種做用,鏈的存在乎義是爲了遍歷)。
一、free list:將free數據頁使用鏈表鏈起來
數據庫剛啓動的時候,lru列表爲空,此時須要用到的時候直接將free列表中的頁刪除,在lru列表中增長相應的頁,維持頁數守恆。
二、lru list:根據冷熱將clean、dirty鏈起來
least recent used(最近最少使用)
一、「中點插入策略」
二、回寫儘可能回寫冷的髒塊
三、覆蓋儘可能覆蓋冷的髒塊
LRU標準算法:
1)3/8的list信息是做爲old list,這些信息是被驅逐的對象。
2)list的中點就是咱們所謂的old list頭部和new list尾部的鏈接點,至關於一個界限。
3)新數據的讀入首先會插入到old list的頭部。
4)若是是old list的數據被訪問到了,這個頁信息就會變成new list,變成young page,就會將數據頁信息移動到new sublist的頭部。
5)在數據庫的buffer pool裏面,無論是new sublist仍是old sublist的數據若是不會被訪問到,最後都會被移動到list的尾部做爲犧牲者。
三、flush list:將頁按照最先髒時間鏈起來
flush list中的也全都是髒頁,刷盤即將flush list中的髒頁刷新回磁盤中。
一、將很是舊的髒塊回寫到磁盤,按照新舊回寫數據頁;
二、由於是從最先髒的塊開始刷,這樣logfile裏的對應的日誌就能夠被覆蓋了。
Q:爲何須要這三種鏈 ?
A:
由於在innodb 緩衝池中,內存管理以下:
一、須要常常找 free 空閒數據塊:free list。
二、須要常常找冷的數據塊:lru list(最近最少使用,根據冷熱鏈起來)。
三、須要知道哪些數據塊是比較早髒的,flush list:咱們要覆蓋舊的 logfile,就須要系統將這些 logfile 對應的髒塊,即將 flush list 鏈上的髒頁往磁盤上刷,(批量往磁盤寫的時候,不如刷髒頁)。
一、設置冷熱分界線:innodb_old_blocks_pct
二、成爲熱塊的所需時間:innodb_old_blocks_time
mysql> show variables like '%old_blocks%'; +------------------------+-------+
| Variable_name | Value |
+------------------------+-------+
| innodb_old_blocks_pct | 37 |
| innodb_old_blocks_time | 1000 |
+------------------------+-------+
2 rows in set (0.01 sec)
經過 innodb_old_blocks_pct 參數值得設定分爲兩部分:一是存放長時間未被訪問的數據頁,二是存放最近被訪問的數據頁。靠近 LRU 鏈表頭部的數據頁表示最近常常被訪問,靠近尾部表示數據頁長期未被訪問,這兩個部分的交匯處稱爲 midpoint,即 innodb_old_blocks_pct這個點的設置。默認是37%,最小是5,最大是95;若是內存比較大的話,能夠將這個數值調低,一般會調成20,也就是說20%的是冷數據塊。目的是爲了保護熱區數據不被刷出內存。
經過innodb_old_blocks_time參數來控制成爲熱數據的所需時間,默認是1000ms,也就是1s,也就是數據在1s內沒有被刷走,就調入熱區。
三、LRU冷熱數據的監控
mysql> show engine innnodb status\G …… Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
一、數據頁從冷到熱,稱爲young;not young就是數據在沒有成爲熱數據狀況下就被刷走的量(累計值)。
二、non-youngs/s,這個數值若是很高,通常狀況下就是系統存在嚴重的全表掃描,天然意味着很高的物理讀。
三、youngs/s,若是這個值相對較高,最好增長一個innodb_old_blocks_time,下降innodb_old_blocks_pct,保護熱數據。