咱們知道InnoDB採用Write Ahead Log策略來防止宕機數據丟失,即事務提交時,先寫重作日誌,再修改內存數據頁,這樣就產生了髒頁。既然有重作日誌保證數據持久性,查詢時也能夠直接從緩衝池頁中取數據,那爲何還要刷新髒頁到磁盤呢?若是重作日誌能夠無限增大,同時緩衝池足夠大,可以緩存全部數據,那麼是不須要將緩衝池中的髒頁刷新到磁盤。可是,一般會有如下幾個問題:mysql
事實上,當數據庫宕機時,數據庫不須要重作全部的日誌,只須要執行上次刷入點以後的日誌。這個點就叫作Checkpoint,它解決了以上的問題:sql
重作日誌被設計成可循環使用,當日志文件寫滿時,重作日誌中對應數據已經被刷新到磁盤的那部分再也不須要的日誌能夠被覆蓋重用。數據庫
InnoDB引擎經過LSN(Log Sequence Number)來標記版本,LSN是日誌空間中每條日誌的結束點,用字節偏移量來表示。每一個page有LSN,redo log也有LSN,Checkpoint也有LSN。能夠經過命令show engine innodb status
來觀察:緩存
--- LOG --- Log sequence number 11102619599 Log flushed up to 11102618636 Last checkpoint at 11102606319 0 pending log writes, 0 pending chkp writes 15416290 log i/o's done, 12.32 log i/o's/second
Checkpoint機制每次刷新多少頁,從哪裏取髒頁,什麼時間觸發刷新?這些都是很複雜的。有兩種Checkpoint,分別爲:服務器
Sharp Checkpoint發生在關閉數據庫時,將全部髒頁刷回磁盤。在運行時使用Fuzzy Checkpoint進行部分髒頁的刷新。部分髒頁刷新有如下幾種:異步
Master Thread以每秒或每十秒的速度從緩衝池的髒頁列表中刷新必定比例的頁回磁盤。這個過程是異步的,不會阻塞查詢線程。async
InnoDB要保證LRU列表中有100左右空閒頁可以使用。在InnoDB1.1.X版本前,要檢查LRU中是否有足夠的頁用於用戶查詢操做線程,若是沒有,會將LRU列表尾端的頁淘汰,若是被淘汰的頁中有髒頁,會強制執行Checkpoint刷回髒頁數據到磁盤,顯然這會阻塞用戶查詢線程。從InnoDB1.2.X版本開始,這個檢查放到單獨的Page Cleaner Thread中進行,而且用戶能夠經過innodb_lru_scan_depth
控制LRU列表中可用頁的數量,默認值爲1024。線程
是指重作日誌文件不可用時,須要強制將髒頁列表中的一些頁刷新回磁盤。這能夠保證重作日誌文件可循環使用。在InnoDB1.2.X版本以前,Async Flush Checkpoint會阻塞發現問題的用戶查詢線程,Sync Flush Checkpoint會阻塞全部查詢線程。InnoDB1.2.X以後放到單獨的Page Cleaner Thread。設計
髒頁數量太多時,InnoDB引擎會強制進行Checkpoint。目的仍是爲了保證緩衝池中有足夠可用的空閒頁。其能夠經過參數innodb_max_dirty_pages_pct
來設置:日誌
mysql> show variables like 'innodb_max_dirty_pages_pct'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | innodb_max_dirty_pages_pct | 90 | +----------------------------+-------+