InnoDB存储引擎Checkpoint

简介

上一篇说到,用户的修改操作会导致innoDB缓冲池出现脏页,如果说每次修改都需要将脏页刷新到磁盘的话,那么这个开销是非常大的。

还有一点,如果将脏页刷新到磁盘时发生了宕机,那么这个数据就无法恢复了,因此innoDB采用了Write Ahead Log策略,事务提交时,先记录到redo log,再修改页,修改完会先缓存到innoDB缓冲池中,通过后台线程去统一刷新。这样既能保证数据安全,又能很大提升性能。

但是,如果redo log无限增大(假设数据库已经运行了好几年的时间),缓冲池页无限大,那么宕机的时候通过整个redo log来恢复数据,这时整个redo log重放恢复的时间将会非常久。

Checkpoint(检查点)技术就来解决以上问题的。

Checkpoint机制

Checkpoint的特点

  • 缩短数据库恢复的时间:

    当数据库发生宕机时,不需要重放整个redo log,只需要重放Checkpoint之后的redo log,这样就可以大大缩短恢复时间;
  • 缓冲池不够用,将脏页刷新到磁盘:

    缓冲池不够用时,根据LRU算法会淘汰掉最近最少使用的页,如果该页是脏页的话,会强制执行CheckPoint,将该脏页刷回磁盘;
  • redo log不可用时,将脏页刷新到磁盘:

    由于重做日志不可能无限大,innoDB重做日志的设计按照循环使用规则,已经不再需要的日志可以被重用。因此如果重做日志经过一圈写到当前Checkpoint的位置,导致redo log不可用,将强制执行CheckPoint,将缓冲池的页至少刷新到当前重做日志的位置。

LSN

LSN(Log Sequence Number)用来标记版本,8个字节的数字。重做日志每增加多少个字节,LSN就递增多少。存放位置:

  • redo log:每次事务提交,先在log buffer生成LSN,然后刷新到磁盘的redo log,递增LSN;
  • 缓冲池中的页:保存两个LSN,第一次修改时LSN最后一次修改时LSN;每次修改页,递增最后一次修改时LSN
  • Checkpoint:每次将页刷新到磁盘,保存该页的第一次修改时LSN

因此,数据库恢复时,只需要重放redo log的LSN - Checkpoint的LSN之间的操作。

Checkpoint类型

Checkpoint类型分为:

  • Sharp Checkpoint:发生在数据库关闭时将所有的脏页都刷新回磁盘,如果此时数据库脏页非常多,则会很大影响性能;

  • Fuzzy Checkpoint:默认方式,只刷新一部分脏页,不是刷新所有脏页;主要有以下几种情况:

    • Master Thread Checkpoint:每秒或者10秒的频率异步刷新缓冲池的脏页到磁盘。(由Page Cleaner Thread完成)
    • FLUSH_LRU_LIST Checkpoint:缓冲池不够用时,根据LRU算法会淘汰掉最近最少使用的页,如果该页是脏页的话,会强制执行CheckPoint,将该脏页刷回磁盘(由Page Cleaner Thread完成);
    • Async/Sync Flush Checkpoint:重做日志不可用的情况,需要强制从脏页列表中选取一些脏页刷新磁盘到缓存(由Page Cleaner Thread完成)。

    假设将已经写到redo log的LSN记为redo_lsn,将已经刷新回磁盘最后一个脏页的LSN记为checkpoint_lsn(严格讲是最后一个脏页的第一次修改时LSN),则可定义:

    checkpoint_age = redo_lsn - checkpoint_lsn;
    async_water_mark = 75% * total_redo_log_file_size;
    sync_water_mark = 90% * total_redo_log_file_size;
    #若total_redo_log_file_size = 2G,则async_water_mark=1.5G,sync_water_mark=1.8G
    

如果checkpoint_age
如果async_water_mark
如果sync_water_mark

  • Dirty Page too much Checkpoint:即脏页数量太多,导致强制进行Checkpoint。由参数innodb_max_dirty_pages_pt来控制,默认75(即75%)。当脏页数量占据75%缓冲池时,刷新一部分脏页到磁盘。(由Page Cleaner Thread完成)

几个重要参数

[图片上传失败...(image-d8c938-1605143370415)]

  • Log sequence number:最新的LSN,存放在Log Buffer;
  • Log flushed up to:redo log上面的LSN,从Log Buffer刷新到redo log;
  • Pages flushed up to:最后一个脏页被刷回磁盘的最后一次修改时LSN
  • Last checkpoint at:checkpoint LSN,即最后一个脏页被刷回磁盘的第一次修改时LSN

四者之间的关系:Log sequence number >= Log flushed up to >= Pages flushed up to >= Last checkpoint at

为什么checkpoint LSN要记录最后一个脏页被刷回磁盘的第一次修改时LSN而不是记录最后一个脏页被刷回磁盘的最后一次修改时LSN

笔者认为,由于Flush list是来管理脏页列表,通过指针指向LRU的脏页,并按照脏页第一次修改时LSN进行排序。页的刷新顺序也算是按照Flush list排序规则,先刷出最旧的脏页。假设有这么一个场景,页1的LSN第一次被设置为10000,页2的LSN第一次被设置为20000,接着页1的LSN被修改为21000,此时页1被刷到磁盘,页2没有刷到磁盘,那么checkpoint LSN = 21000;而在这之后机器突然间挂了,重启恢复就会从21000开始恢复,就会导致之前页2的数据无法恢复。

你可能感兴趣的:(InnoDB存储引擎Checkpoint)