InnoDB的Checkpoint技术
前言
前面介绍InnoDb体系架构时介绍过InnoDb中内存中有一块缓冲池,缓冲池是用来协调CPU速度与磁盘速度的鸿沟。因此页的操作首先都是在缓冲池中完成的。如果一条DML语句,如Update或Delete改变了页中的记录,那么此时页是脏的,即缓冲池中的页的版本要比磁盘的新。数据库需要将新版本的页从缓冲池刷新到磁盘。但使用缓冲池的设计需要研究以下一些问题:
- 倘若每次一个页发生变化,就将新页的版本刷新到磁盘,那么这个开销是非常大的。若热点数据集中在某几个页中,那么数据库的性能将变得非常差。
- 如果在从缓冲池将页的新版本刷新到磁盘时发生了宕机,那么数据就不能恢复了。
为了避免发生数据丢失的问题,当前事务数据库系统普遍都采用了Write Ahead Log策略,即当事务提交时,先写重做日志,再修改页。当由于发生宕机而导致数据丢失时,通过重做日志来完成数据的恢复。这也是事务ACID中D ( Durability持久性〉的要求。
Checkpoint
Checkpoint解决的问题
- 缩短数据库的恢复时间
当数据库发生宕机时,数据库不需要重做所有的日志,因为Checkpoint之前的页都已经刷新回磁盘。故数据库只需对Checkpoint后的重做日志进行恢复。这样就大大缩短了恢复的时间。 - 缓冲池不够用时,将脏页刷新到磁盘
当缓冲池不够用时,根据LRU算法会溢出最近最少使用的页,若此页为脏页,那么需要强制执行Checkpoint,将脏页也就是页的新版本刷回磁盘。 - 重做日志不可用时,刷新脏页。
重做日志出现不可用的情况是因为当前事务数据库系统对重做日志的设计都是循环使用的,并不是让其无限增大的。重做日志可以被重用的部分是指这些重做日志已经不再需要,即当数据库发生宕机时,数据库恢复操作不需要这部分的重做日志,因此这部分就可以被覆盖重用。若此时重做日志还需要使用,那么必须强制产生Checkpoint,将缓冲池中的页至少刷新到当前重做日志的位置。
checkpoint的两种方式
- Sharp Checkpoint
Sharp Checkpoint 发生在数据库关闭时将所有的脏页都刷新回磁盘,这是默认的工作方式,即参数innodb_fast_shutdown=1。 - Fuzzy Checkpoint
若数据库在运行时也使用Sharp Checkpoint,那么数据库的可用性就会受到很大的影响。故使用Fuzzy Checkpoint进行页的刷新,即只刷新一部分脏页,而不是刷新所有的脏页回磁盘。
在InnoDB存储引擎中可能发生如下几种情况的FuzzyCheckpoint:
–> Master Thread Checkpoint
对于Master Thread 中发生的Checkpoint,差不多以每秒或每十秒的速度从缓冲池的脏页列表中刷新一定比例的页回磁盘。这个过程是异步的,即此时InnoDB存储引擎可以进行其他的操作,用户查询线程不会阻塞。
–> FLUSH_LRU_LIST Checkpoint
因为InnoDB存储引擎需要保证LRU列表中需要有一定数量的空闲页可供使用。Page Cleaner线程会检查LRU列表中是否有足够的可用空间,倘若没有100个可用空闲页,则将LRU列表尾端的页移除。如果这些页中有脏页,则需要进行Checkpoint,而这些页是来自LRU列表的,因此称为FLUSH_LRU_LIST Checkpoint。
–> Async/Sync Flush Checkpoint
重做日志文件不可用时,需要强制将一些页刷新回磁盘,而此时脏页是从脏页列表中选取的。可见,Async/Sync Flush Checkpoint是为了保证重做日志的循环使用的可用性。这部分操作也是在Page Cleaner线程处理的。
–> 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: 90.000000
1 row in set (0.01 sec)
innodb_max_dirty_pages_pct值为90表示当缓冲池中脏页的数量占据90%时,强制进行Checkpoint,刷新一部分的脏页到磁盘。