MySQL为了提高性能,你对它数据行的增、删、改操作其实都优先发生在内存(Buffer Pool)中。那你想,假如你update了某些数据,Buffer Pool中的数据页也就会被你改成脏数据页。那万一你刚修改完并提交了事物,还没来得及将数据落盘MYSQL就宕机了怎么办?
当MySQL重启的时候需要把方才修改的内容恢复出来吧,不然数据就不一致了。那怎么恢复呢?就借助redo log恢复。因为前面说了,当你begin事物开始操作时,会先写redo log,在操作数据页。这个数据恢复的过程也叫做重做。
checkpoint机制
随着MySQL的运行,Buffer Pool中的数据页会被修改成脏数据页,当你开启事物进行一系列的操作时MySQL会为你不停的记录一堆日志,拿redolog来说,rodo log也是需要往先往内存中写,再以块的形式刷新回磁盘。
无论怎样都会存在这样一个中间过程:内存中存在脏数据页、和脏日志未来得及刷新回磁盘。
而本小节中要说的Checkpoint机制就是将这些脏数据刷新回磁盘的机制,即只要发生Checkpoint,就要将脏数据刷新回磁盘,反过来,当MySQL重启时会去找Checkpoint,并且根据Checkpoint的特性。MySQL可以明确的知道checkponit之前的脏数据已经落过盘了,重启时没必要进行重做。看到这里你已经大概知道Checkpoint是什么了。我们在稍微总结一下Checkpoint机制的作用:
- 所谓的崩溃恢复,其实就是MySQL重启时照着redo log中的最后一次Checkpoint之后的日志回放一遍
- 因为Checkpoint会不断的更新,并且MySQL重启时只需要对Checkpoint之后的数据进行恢复,所以Checkpoint会缩短MySQL重启的时间。
- 因此每次进行Checkpoint时buffer pool中的脏数据页、redo log中的脏日志都会落盘。所以Checkpoint实际上起到了为这两者进行瘦身的作用。维持两个的可用性。
LSN
LSN全称是:log sequence number。关于什么是LSN没什么难以理解的,它就是一个序列号。并且表空间中的数据页、缓存页、内存中的rodo log、磁盘中的redo log以及checkponit都有LSN标记。LSN又啥用呢?比如MySQL重启时会对比数据页的LSN和redo log的LSN的大小,如果前者的LSN比后者小。说明数据页中缺失了一部分数据。如果满足其他数据恢复的条件,MySQL就会将LSN之后的这些redo 进行一次回方,完成数据的恢复。
让我们从几张图理解一下LSN与checkpoint。
前面说了表空间中的数据页、内存中的缓存页、内存中的redo log、磁盘中的redo log、checkpoint它们五者都有记录LSN。所以你可以看到,在12:00:00时刻,它们五者中的LSN都是100。
然后在12:00:00时刻你开启了一个事物,执行update语句,你的CRUD都优先发生在内存中,也就是buffer pool中。并且在修改内存中的数据前先记录redo log,所以buffer pool中的缓存页和内存中的redo log的LSN率先被更新成110。
紧接着你的事物中又执行了delete语句,同样的道理内存中的redo log和缓存页的LSN被更新为150。接着时间来到了12:00:01。触发了由参数innodb_flush_log_at_timeout(默认1s)redo log刷盘机制。redo log会部分落盘,所以上图中的磁盘上的redo log的lSN更新为150。
接着你的事物中又执行了一次delete语句。同理内存中的缓存页和内存中的redo log的LSN被更新成了300。
终于checkpoint机制触发了!checkpoint机制的触发意味着要将内存中所有脏数据落盘。因此内存中的缓存页磁盘成为磁盘上的数据页,也就是说磁盘上的数据页的LSN变成300。同理磁盘上的redo log的LSN变成300。checkpoint的LSN也更新成300。
然而你的事物并没有结束,你在12:00:02时刻又insert了一条数据,同上面的原因内存中的缓存页、内存中的redo log 的LSN被更新成800。
终于你的要提交事物了!默认情况下,事物提交时,redo log会落盘,但是内存中的脏数据并不会落盘。所以磁盘上的redo log LSN被更新成800。也就是说此时除了表空间中的数据页的LSN、checkpoint的LSN其他的LSN均已达到最新的800。
最后checkpoint再次出现。这五者LSN重新保持一致。