Mysql InnoDB Redo log( 四 )


flushed_to_disk_lsn记录刷新到磁盘的redo log 日志量

Mysql InnoDB Redo log

文章插图
当存在新的日志写入到log buffer的时候 , 首先lsn(log squence number记录当总共写入的redo 日志量)会增大 , 但是flushed_to_disk_lsn大小不变(因为没刷盘)随着log buffer中的内容刷新到磁盘 , flushed_to_disk_lsn将随之增大 , 当flushed_to_disk_lsn = lsn的时候说明所有log buffer中的日志都刷新到了磁盘
6.buffer pool 中flush 链表中的lsnMTR是对底层页面的一次原子访问 , 在访问过程中会产生一组不可以分割的redo log , 在MTR结束的时候会把这一组redo log记录到log buffer中 。除此之外在MTR结束的时候还需要:把MTR执行过程中修改的页面加入到Buffer pool中的flush链表中 , 毕竟刷新脏页到磁盘是buffer pool的任务 。
当这个页面第一次被修改的时候就会将其对应的控制块插入到flush 链表头部 , 后续再次修改不会移动控制块 , 因为其已经在flush 链表中 , 所有说flush 链是按照页面第一次修改的时间进行排序的 , 在这个过程中会记录两个重要的属性到脏页的控制块中:
  • oldest_modification
    第一次修改修改buffer pool某个缓冲页(先把页读到buffer pool的缓冲页 , 然后进行修改)时 , 记录下修改该页面MTR开始时对应的lsn(注意这个开始时)
  • newest_modification
    每次修改页面 , 都会记录下修改该页面MTR结束时的lsn,该属性记录最近一次修改后对应的lsn
例如第一个MTR1修改了页A , 在oldest_modification记录下开始时的lsn为8716 , newest_modification记录下MTR1结束时的lsn
Mysql InnoDB Redo log

文章插图
MTR2后续修改了页B和页C , 页B , 页C最开始不在flush链表中 , 背修改后加入到链表的头部 , 也就是说 , 越靠近头部 , 修改的时间就越晚 , 如下:
Mysql InnoDB Redo log

文章插图
如果此时在flush链表中的页被修改 , 只需要更新newest_modification即可 。flush链表按照第一次被更新时候的lsn排序 , 也就是按照oldest_modification进行排序 , 多次修改位于flush链表中的页只会更新其newest_modification
7.checkpoint由于redo log日志文件文件是有限的 , 所有需要循环使用redolog 日志文件组中的文件 。redo log存在的目的是系统崩溃后恢复脏页 , 如果对应的脏页已经刷新到磁盘中 , 那么即使系统崩溃 , 重启之后页不需要使用redo log恢复该页面看 , 对应的redo log日志也没存在的必要了 , 占用的磁盘空间可以进行重复使用 , 被其他redo log日志覆盖 。那么如何判断哪些redo 日志占用的磁盘空间可以覆盖昵 , 其对应的脏页已经刷新到磁盘了昵?
innodb使用checkpoint_lsn记录可以被覆盖的redo log日志总量
Mysql InnoDB Redo log

文章插图
假如页A已经被刷新到磁盘了 , 那么页A对应的控制块会从flush链表中移除 , MTR1生成的日志可以被覆盖了 , 就进行一个增加checkpoint_lsn的操作 , 这个过程称作执行一次checkpoint(刷新脏页到磁盘和执行一次checkpoint是两回事 , 通常是不同线程上执行的 , 并不意味着每次刷新脏页的时候都会执行一次checkpoint)

经验总结扩展阅读