MySQL教程:关于checkpoint机制(2)

checkpoint_age>sync_water_mark这种情况一般很少发生,除非设置的重做日志文件太小,并且在进行类似LOAD DATA的BULK INSERT操作。此时触发Sync Flush操作,从Flush列表中刷新足够的脏页回磁盘,使得刷新后满足checkpoint_age<async_water_mark。

可见,Async/Sync Flush Checkpoint是为了保证重做日志的循环使用的可用性。在InnoDB 1.2.x版本之前,Async Flush Checkpoint会阻塞发现问题的用户查询线程,而Sync Flush Checkpoint会阻塞所有的用户查询线程,并且等待脏页刷新完成。从InnoDB 1.2.x版本开始——也就是MySQL 5.6版本,这部分的刷新操作同样放入到了单独的Page Cleaner Thread中,故不会阻塞用户查询线程。

MySQL官方版本并不能查看刷新页是从Flush列表中还是从LRU列表中进行Checkpoint的,也不知道因为重做日志而产生的Async/Sync Flush的次数。但是InnoSQL版本提供了方法,可以通过命令SHOW ENGINE INNODB STATUS来观察,如:

mysql> show engine innodb status \G

BUFFER POOL AND MEMORY

----------------------

Total memory allocated 2058485760; in additional pool allocated 0

Dictionary memory allocated 913470

Buffer pool size  122879

Free buffers      79668

Database pages    41957

Old database pages 15468

Modified db pages  0

Pending reads 0

Pending writes: LRU 0, flush list 0, single page 0

Pages made young 15032929, not young 0

0.00 youngs/s, 0.00 non-youngs/s

Pages read 15075936, created 366872, written 36656423

0.00 reads/s, 0.00 creates/s, 0.90 writes/s

Buffer pool hit rate 1000 / 1000, young-making rate 0 / 1000 not 0 / 1000

Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s

LRU len: 41957, unzip_LRU len: 0

I/O sum[39]:cur[0], unzip sum[0]:cur[0]


4、Dirty Page too much

即脏页的数量太多,导致InnoDB存储引擎强制进行Checkpoint。其目的总的来说还是为了保证缓冲池中有足够可用的页。其可由参数innodb_max_dirty_pages_pct控制:

mysql> SHOW GLOBAL VARIABLES LIKE 'innodb_max_dirty_pages_pct' ;

+----------------------------+-------+

| Variable_name              | Value |

+----------------------------+-------+

| innodb_max_dirty_pages_pct | 75    |

+----------------------------+-------+


innodb_max_dirty_pages_pct值为75表示,当缓冲池中脏页的数量占据75%时,强制进行Checkpoint,刷新一部分的脏页到磁盘。在InnoDB 1.0.x版本之前,该参数默认值为90,之后的版本都为75。

三、Checkpoint机制

在Innodb事务日志中,采用了Fuzzy Checkpoint,Innodb每次取最老的modified page(last checkpoint)对应的LSN,再将此脏页的LSN作为Checkpoint点记录到日志文件,意思就是“此LSN之前的LSN对应的日志和数据都已经flush到redo log

当mysql crash的时候,Innodb扫描redo log,从last checkpoint开始apply redo log到buffer pool,直到last checkpoint对应的LSN等于Log flushed up to对应的LSN,则恢复完成

那么具体是怎么恢复的呢?

MySQL教程:关于checkpoint机制

 

如上图所示,Innodb的一条事务日志共经历4个阶段:

创建阶段:事务创建一条日志;

日志刷盘:日志写入到磁盘上的日志文件;

数据刷盘:日志对应的脏页数据写入到磁盘上的数据文件;

写CKP:日志被当作Checkpoint写入日志文件;


对应这4个阶段,系统记录了4个日志相关的信息,用于其它各种处理使用:

Log sequence number(LSN1):当前系统LSN最大值,新的事务日志LSN将在此基础上生成(LSN1+新日志的大小);

Log flushed up to(LSN2):当前已经写入日志文件的LSN;

Oldest modified data log(LSN3):当前最旧的脏页数据对应的LSN,写Checkpoint的时候直接将此LSN写入到日志文件;

Last checkpoint at(LSN4):当前已经写入Checkpoint的LSN;

对于系统来说,以上4个LSN是递减的,即: LSN1>=LSN2>=LSN3>=LSN4.

具体的样例如下(使用show innodb status \G命令查看,Oldest modified data log没有显示):

LOG

---

Log sequence number 34822137537

Log flushed up to  34822137537

Last checkpoint at  34822133028

0 pending log writes, 0 pending chkp writes

54189288 log i/o's done, 3.00 log i/o's/second 


四、日志保护机制

mysql crash的时候,Innodb有日志刷盘机制,可以通过innodb_flush_log_at_trx_commit参数进行控制,这里说的是如何防止日志覆盖导致日志丢失

Innodb的checkpoint和redo log有哪些紧密关系?有几上名词需要解释一下:

Ckp age(动态移动): 最老的dirty page还没有flush到数据文件,即没有做last checkpoint的范围

Buf age(动态移动): modified page information没有写到log中,但已在log buffer

Buf async(固定点): 日志空间大小的7/8,当buf age移动到Buf async点时,强制把没有写到log中的modified page information开始写入到log中,不阻塞事务

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/ed1d49c117de6f7dfcbcf68cdae833bd.html