https://www.jianshu.com/p/57a1dcf39b88
一直弄不清楚LSN和checkpoint的意思
个人理解:当要把buffer_pool里的脏页刷入磁盘的时候,会用checkpoint记录刷入内容,刷入到哪里了。防止下次忘记刷入内容,刷入到哪里了。checkpoint就是一个数字,每当刷入内容,就会写入日志,然后用一个数字来记录日志和内容写入到哪里了,这个数字是一直增加的。
redo日志里有LSN,页里面也有LSN。checkpoint记录在redo日志里。
当update执行的时候,会写入很多日志信息到redo日志。先写入到redo日志buffer,就是内存缓存中。更新的内容先会更新buffer里面的页。因为redo日志有写盘更新机制,基本都是一有写入buffe,就会写入磁盘。所以redo磁盘日志会时时记录LSN这一串数字。
只有当条件达到了,才会执行checkpoint,把脏页写入磁盘。当所有脏页写入磁盘后,会把checkpoint写入到redo日志。而写入磁盘的每一个页,都记录一个LSN的。
当mysql突然挂了,如何做数据一致性呢?
mysql启动之后,会检测redo日志里面的checkpoint,就知道最后写入磁盘的页的LSN都是小于等于这个checkpoint的。就是记录着大于checkpoint的LSN的页,都没及时写入到磁盘,都丢失了。此时内容需要从redo日志获取,利用redo日志进行数据一致性。
通过 show engine innodb status\G; 查看LSN和checkpoint
redo日志无法对已经损坏的页进行修复,所以如果在写入数据的时候,比如一次IO写入16K,文件系统block是4k,磁盘IO是512k。那么mysql进行了一次写入,16k,但是当写入了4k,突然mysql挂了,那么还有12k是没有写入。导致mysql这个页的数据有问题,页损坏了。此时redo无法修复。
doublewrite的过程是,把脏页写入磁盘的过程,先写入内存的doublewrite buffer,然后内存的doublewrite buffer先写一份到共享表空间的double write里。然后再写一份到相对应的表空间里。如果此时突然mysql挂了,mysql重启的时候,这个页的数据从共享表空间那边copy一份过来恢复就行了。