CheckPoint技术简介

缓冲池中的数据由于脏页的存在,一般来说版本都要新于磁盘中的,因此最终需要把脏页数据刷新进磁盘。但是如果每产生一页脏页就刷新一页脏页,由于磁盘的性能导致这样的效率是非常低的。而且如果这样操作的过程中还发生了宕机,那么脏页中的数据就会丢失而无法恢复了。因此,现在的事务数据库系统都会采用Wirite Ahead Log策略,即当事务提交时,先写重做日志,再修改样页,即使发生了宕机也可以通过重做日志来恢复数据。重做日志除了可以恢复数据,还可以把脏页的刷新记录下来,无需采用脏页一产生就刷新进磁盘这种效率极低的策略,可以后续再刷新回磁盘。

但是,由于重做日志的内存空间不可能无限大,并且缓冲池也不能缓存数据库中的所有数据,因此不可能说把脏页一直放在缓冲池并写入重做日志。即使上面两个假设条件都成立,由于重做日志量极大,脏页的刷新时间一定要很久,如果这时候又发生了宕机,那岂不是非常伤,又要重新来一次长时间的刷新。因此,为了解决上面的几个问题,就出现了CheckPoint技术,它主要是为了是脏页刷新量和刷新时间控制在一定的合理值内。因此,CheckPoint(检查点)技术的目的如下:

  • 缩短数据库的恢复时间
  • 缓冲池不够用时,将脏页刷新到磁盘
  • 重做日志不可用时,刷新脏页

CheckPonit点记录在重做日志中,该点之前的日志已经完成了重做,因此只需要重做该点之后的日志即可,这样可以当发生宕机之后无需再从头开始做起,大大缩短了数据库的恢复时间。
当缓冲池内存不够时,根据LRU算法会溢出非热点页,如果这里面包含了脏页,就会将脏页刷新到磁盘并使CheckPoint点向后移动。
当重做日志的内存不够时,会强制执行CheckPoint后的日志,并刷新到磁盘,以便使重做日志能够写入新的日志。

InnoDB存储引擎内部,两种checkpoint,分别为:

  • Sharp Checkpoint
  • Fuzzy Checkpoint

Sharp Checkpoint

Sharp Checkpoint发生在数据库关闭时,将所有的脏页都刷新回磁盘,这是默认的工作方式,即配置文件中的参数:innodb_fast_shutdown=1。但是这不适用于数据库运行时的刷新。

Fuzzy Checkpoint

在数据库运行时,InnoDB存储引擎内部采用Fuzzy Checkpoint,只刷新一部分脏页。并且Fuzzy CheckPonit是一种异步刷新,不会影响到其它的线程,一般发生在下面的四种情况。

MasterThread Checkpoint

主线程每秒或每10秒从缓冲池脏页列表刷新一定比例的页回磁盘,并且这是异步刷新,即此时InnoDB存储引擎可以进行其他操作,用户查询线程不会受阻。

FLUSH_LRU_LIST Checkpoint

InnoDB存储引擎需要保证LRU列表中差不多有100个空闲页可供使用。在InnoDB 1.1.x版本之前,用户查询线程会检查LRU列表是否有足够的空间操作,如果没有,根据LRU算法,溢出LRU列表尾端的页,如果这些页有脏页,需要进行checkpoint。因此叫:flush_lru_list checkpoint。
InnoDB 1.2.x开始,这个检查放在了单独的进程(Page Cleaner)中进行。好处是减少master Thread的压力和减轻用户线程阻塞。
设置参数:innodb_lru_scan_dept:控制LRU列表中可用页的数量,该值默认1024

Async/Sync Flush Checkpoint

重做日志文件不够用时,需要强制进行日志刷新。

Dirty Page too much Checkpoint

脏页太多,强制checkpoint,保证缓冲池有足够可用的页。当缓冲池脏页数量占据75%时会强制执行该方式的CheckPoint,InnoDB存储引擎的默认值也是75%。

Master Thread的工作方式

Master Thread具有最高的线程优先级,内部由多个循环组成主循环(loop)、后台循环(backgroud loop)、刷新循环(flush loop)和暂停循环(suspend loop),Master Thread会根据数据库运行的状态在这几个循环中切换。

主循环

大多数的操作是在这个循环中进行的,其中有两大部分的操作——每秒钟和每十秒的操作。每秒钟和每十秒的操作是不精确的,在负载很大的情况下可能会有延迟,只能说大概在这个频率下。

每一秒操作

  • 日志缓冲刷新到磁盘,即使这个事务还没有提交(总是)
    事务没有提交,InnoDB仍然每秒会将重做日志缓冲中的内容刷新到重做日志文件,这可以很好的解释大事务提交时间短的原因。
  • 合并插入缓冲(可能)
    合并插入缓冲(Insert Buffer)并不是每秒都会发生的。InnoDB会判断前一秒的IO次数是否小于5次,小于5次则进行合并缓冲的操作。
  • 至多刷新100个InnoDB的缓冲池的脏页到磁盘(可能)

    1. 不是每秒都会发生,InnoDB会判断当前缓冲池中脏页的比例是否超过了配置文件中的参数 ,如 <br /> 果超过了这个法治,InnoDB会认为需要做磁盘同步的操作,将100个脏页写入磁盘中。
  • 如果当前没有用户活动,则切换到background loop(可能)

    每十秒操作

  • 刷新100个脏页到磁盘(可能)
    InnoDB会判断过去10秒钟内磁盘到IO操作是否小于200次,如果是,InnoDB将100个脏页刷新到磁盘。

  • 合并至多5个插入缓冲(总是)
    InnoDB会合并插入缓冲。
  • 将日志缓冲刷新到磁盘(总是)
    InnoDB在进行一次将日志缓冲刷新到磁盘的操作,这和每秒一次时发生的操作是一样的。
  • 删除无用的undo页(总是)
    InnoDB会执行full purge操作,删除无用的Undo页。InnoDB会判断当前事务系统中已被删除的行是否可以删除,如果可以,立即删 除。在执行full purge操作时,每次最多尝试回收20个undo页。
  • 刷新100个或者10个脏页到磁盘(总是)
    InnoDB会判断缓冲池中脏页的比例,如果有超过75%的脏页,则刷新100页脏页到磁盘,如果小于75%,只需要刷新10%磁盘。

    后台循环

    如果当前没有用户活动或者数据库关闭时就会切换到这个线程,后台循环一般会执行下列操作:

  • 删除无用的Undo页(总是)

  • 合并20个插入缓冲(总是)
  • 跳回到主循环(总是)
  • 不断刷新100个页直到符合条件(可能,这点跳转到刷新循环中完成)

    刷新循环

    不断刷新脏页的循环,如果这个循环没什么事情可做了,则会切换到suspend暂停循环。最新的InnoDB存储引擎版本独立了一条Page Cleaner Thread来分担Master Thread在该循环的压力。

    暂停循环

    将master Thread线程挂起,等待事件发生。若用户启动了InnoDB存储引擎,却没有使用任何InnoDB存储引擎的表,那么Master Thread总是处于挂起的状态。