redo日志(有问题,待修改)

redo日志(物理日志)

InnoDB存储引擎是以页为单位来管理存储空间的,我们进行的增删改查操作都是将页的数据加载到内存中,然后进行操作,再将数据刷回到硬盘上。

那么问题就来了,如果我要给张三转账100块钱,事务已经提交了,这个时候InnoDB把数据加载到内存中,这个时候还没来得及刷入硬盘,突然停电了,数据库崩了。重启之后,发现我的钱没有转成功,这不是尴尬了吗?

解决方法很明显,我们在硬盘加载到内存之后,进行一系列操作,一顿操作猛如虎,还未刷新到硬盘之前,先记录下,在XXX位置我的记录中金额减100,在XXX位置张三的记录中金额加100,然后再进行增删改查操作,最后刷入硬盘。如果未刷入硬盘,在重启之后,先加载之前的记录,那么数据就回来了。

这个记录就叫做重做日志,即redo日志。他的目的是想让已经提交的事务对数据的修改是永久的,就算他重启,数据也能恢复出来。

log buffer(日志缓冲区)

为了解决磁盘速度过慢的问题,redo日志不能直接写入磁盘,咱先整一大片连续的内存空间给他放数据。这一大片内存就叫做日志缓冲区,即log buffer。到了合适的时候,再刷入硬盘。至于什么时候是合适的,这个下一章节说。

我们可以通过show VARIABLES like 'innodb_log_buffer_size'命令来查看当前的日志缓存大小,下图为线上的大小。

redo日志刷盘时机

由于redo日志一直都是增长的,且内存空间有限,数据也不能一直待在缓存中, 我们需要将其刷新至硬盘上。 

那什么时候刷新到硬盘呢?

  •  log buffer空间不足。上面有指定缓冲区的内存大小,MySQL认为日志量已经占了 总容量的一半左右,就需要将这些日志刷新到磁盘上。 
  • 事务提交时。我们使用redo日志的目的就是将他未刷新到磁盘的记录保存起来,防止 丢失,如果数据提交了,我们是可以不把数据提交到磁盘的,但为了保证持久性,必须 把修改这些页面的redo日志刷新到磁盘。 
  • 后台线程不同的刷新 后台有一个线程,大概每秒都会将log buffer里面的redo日志刷新到硬盘上。
  •  checkpoint 下下小节讲

redo日志文件组

我们可以通过show variables like 'datadir'命令找到相关目录,底下有两个文件, 分别是ib_logfile0和ib_logfile1,如下图所示。

 

 

我们将缓冲区log buffer里面的redo日志刷新到这个两个文件里面,他们写入的方式 是循环写入的,先写ib_logfile0,再写ib_logfile1,等ib_logfile1写满了,再写ib_logfile0。 那这样就会存在一个问题,如果ib_logfile1写满了,再写ib_logfile0,之前ib_logfile0的内容 不就被覆盖而丢失了吗? 这就是checkpoint的工作啦。

checkpoint

redo日志是为了系统崩溃后恢复脏页用的,如果这个脏页可以被刷新到磁盘上,那么 他就可以功成身退,被覆盖也就没事啦。

 冲突补习 

从系统运行开始,就不断的修改页面,会不断的生成redo日志。redo日志是不断 递增的,MySQL为其取了一个名字日志序列号Log Sequence Number,简称lsn。 他的初始化的值为8704,用来记录当前一共生成了多少redo日志。

 redo日志是先写入log buffer,之后才会被刷新到磁盘的redo日志文件。MySQL为其 取了一个名字flush_to_disk_lsn。用来说明缓存区中有多少的脏页数据被刷新到磁盘上啦。 他的初始值和lsn一样,后面的差距就有了。

 做一次checkpoint分为两步 

  • 计算当前系统可以被覆盖的redo日志对应的lsn最大值是多少。redo日志可以被覆盖, 意味着他对应的脏页被刷新到磁盘上,只要我们计算出当前系统中最早被修改的oldest_modification, 只要系统中lsn小于该节点的oldest_modification值磁盘的redo日志都是可以被覆盖的。
  •  将lsn过程中的一些数据统计。

作者:学习Java的小姐姐
链接:https://juejin.im/post/5dfc846051882512327a63b6
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
posted @ 2020-04-22 01:18  泥土里的绽放  阅读(256)  评论(0编辑  收藏  举报