checkpoint是为了解决:
- 缩短数据库恢复时间
- 缓冲池不够用时,将脏页刷新到磁盘
- 重做日志不可用时,刷新脏页
所以当数据库发生宕机时,数据库不需要重做所有的日志,因为checkpoint之前的页都已经刷新到磁盘了。数据库只需对checkpoint之后的重做日志进行恢复。
当缓冲池不够用时,根据LRU算法将最近最少使用的脏页,强制执行checkpoint,将脏页刷新到磁盘。
重做日志可以被重用的部分是指这些重做日志不在被需要,即宕机时,数据库恢复操作不需要这部分日志。若重做日志还需要使用,那么必须强制产生checkpoint,将缓冲池中的页至少刷新到当前重做日志的位置。
可以通过show engine innodb status查看LSN
mysql>show engine innodb status\G;
......
LOG
---
Log sequence number 17383720925
Log flushed up to 17383720925
Last checkpoint at 17383720535
innodb有两种checkpoint,分别为:
- sharp
- fuzzy
sharp checkpoint发生在数据库关闭时将所有的脏页都刷新到磁盘,这是默认的工作方式,即参数innodb_fast_shutdown=1
fuzzy checkpoint实在数据库运行时的方式,一次只刷新一部分脏页到磁盘
- 发生fuzzy checkpoint的情况:
- master thread checkpoint
- flush_lru_list checkpoint
- async/sync flush checkpoint
- dirty page too mush checkpoint
master thread中发生checkpoint,以每秒或每十秒从缓冲池的脏页列表中刷新一定比例的页到磁盘。这个过程是异步的。
flush_lru_list checkpoint 是因为innodb要保证lru列表中需要100左右的空闲有可用。如果不足,则把lru列表尾端的也移除,如果其中有脏页,则进行checkpoint。从5.6开始这个过程由page cleaner线程进行,用户可以通过参数innodb_lru_scan_depth来控制lru列表中可用页的数量,默认1024:
mysql> select version();
+------------+
| version() |
+------------+
| 5.6.30-log |
+------------+
1 row in set (0.00 sec)
mysql> show variables like 'innodb_lru_scan_depth'\G;
*************************** 1. row ***************************
Variable_name: innodb_lru_scan_depth
Value: 1024
1 row in set (0.10 sec)
async/sync flush checkpoint指的是重做日志文件不可用的情况,这是需要强制将脏页列表中的一些数据刷新到磁盘。若将已经写入重做日志的LSN记为redo_lsn,将已经刷新回磁盘的最新页LSN记为checkpoint_lsn,则可定义:
checkpoint_age = redo_lsn - checkpoint_lsn
async_water_mark = 0.75 * total_redo_log_file_size
sync_water_mark = 0.9 * total_redo_log_file_size
- 当checkpoint_age < async_water_mark时,不需要刷新任何脏页到磁盘;
- 当async_water_mark < checkpoint_age < sync_water_mark时触发async flush,从flush列表刷新足够的脏页回磁盘,使得刷新后满足checkpoint_age < async_water_mark;
- checkpoint_age > sync_water_mark很少发生,除非设置的重做日志文件太小,并且进行类似load data的bulk insert操作。此时出发sync flush操作,从flush列表刷新足够的脏页回磁盘,使得刷新后满足checkpoint_age < async_water_mark;
async/sync flush checkpoint是为了保证重做日志循环使用的可用性。
dirty page too much checkpoint,即脏页数量太多,导致innodb存储引擎强制进行checkpoint。主要还是为了保证缓冲池有足够可用的页。可由参数innodb_max_dirty_pages_pct控制
mysql> show variables like 'innodb_max_dirty_pages_pct'\G;
*************************** 1. row ***************************
Variable_name: innodb_max_dirty_pages_pct
Value: 75
1 row in set (0.08 sec)