checkpoint机制,主要干的事情就是把脏页刷新到磁盘。
数据库只能保证最终一致性。你在数据库运行的时候,磁盘上的数据和内存中的数据不一致太正常了。
另外checkpoint也能保证数据库在挂了,或者出事了之后,缩短他的恢复时间。这个很好理解,MySQL有redo和binlog去保证事务的持久性。所以即使你数据没有落盘,也没关系,他是有日志的。但是,如果没有checkpoint,你日志跑了1周,这时候你MySQL挂了,你重做日志需要多久。这个是很慢的。所以checkpoint能保证数据能有效地落盘,缩短recover时间。
而内存中这么多页,MySQL怎么知道哪些是脏页需要落盘,哪些不是脏页。这就引出了我们之前说的flush list。
首先,每个页有一个LSN,而MySQL整个实例,有一个全局的LSN,你可以把这个LSN理解成checkpoint,最后redo log里还有一个LSN。整个MySQL体系下,就这三个地方有LSN。
这么聊很难理解,我举一个例子。
page 1 被加载到bp里,初始的lsn是100,然后这个页被修改了,事务提交了。假设此时MySQL全局lsn是200,那么page 1的lsn被修改为200,并且写入redo log。
过了一段时间 page 2被加载到bp里,初始的lsn是110,然后这个页也被修改了,事务提交了。假设此时MySQL全局lsn是500,那么page 2的lsn被修改为500,并写入redo log。
然后,下一个时间,触发checkpoint。page 1作为最后一页被写入进磁盘了。page 2没有被写入。紧接着,mysql挂了。那么MySQL再次启动时,就会重放200-500之间的lsn。
而这个lsn究竟代表的是什么?
其实代表的是此次操作所产生的log字节数。
然后lsn你可以show engine innodb status\G查看,在log部分下
last checkpoint at就是当前最后一次进行checkpoint位置的lsn。
page flushed up to 就是当前最大或者说是最新的刷新到磁盘上的lsn。
log sequence number 表示当前内存中redo log buffer的lsn。
log flushed up to表示刷新到redo log上的lsn。
原则上last checkpoint at <= page flushed up to
比如说,我有一个页,lsn80,被加载到内存。此时全局lsn是100。这时候,这个页被修改了,产生了20字节的log。那么这个页lsn变成120,并且被放到flush list中。
然后这个页又被修改了,又多了20字节的log。此时lru list中这个页lsn是140。但是flush list中,这个页的lsn是不会变的。因为flush list的组织方式,是用的这个页第一次被加载进来的lsn来组织的。
所以这时候,第一个lsn是120,下面的三个lsn是140.
之前有提到innodb_buffer_page_lru这个表。其中有两个字段,NEWEST_MODIFICATION 和 OLDEST_MODIFICATION。
后者表示页第一次被更新时的lsn,前者是内存中最新的lsn。
未完待续