00:00
好,那同学们,咱们讲完这个事物的基础知识之后呢,咱们来看一下MYSQ的这个事物日志啊,看一下这一章。这个在上一章当中啊,咱们提到说事物呢,有四个特性啊,叫acid的特性,对吧,那么这四个特性呢,应该说呢,跟我们这个事物呢,就是一个等价的关系了,那这四个特性是如何进行保证的呢?这里边儿就提到了这个隔离性啊,是由这个锁机制呢来实现的,那锁机制的话呢,咱们放到下一章呢去来讲解,这个内容量还不少的啊,有一定的难度,好那么除了这个隔离性之外呢,剩下的这三个特性我们该如何呢去保证呢?啊这呢就提到了说日志了啊,这个日志呢,因为是跟我们事物相关的日志了,所以咱们就放在这来讲,剩下的一些日志呢,咱们是放到后边这个章节里边呢去说的。那么这里呢,就提到了两种日志,一个呢叫做redo日志,一个呢叫做安度日志啊redo日志呢,就是音译过来就叫做重做日志啊,叫重做日志,它呢提供在写入的操作,恢复提交事物修改的页的操作啊,用来保证事物的持久性。
01:01
啊,它来保证持久性,然后这个安度日志呢,诶这个音译过来,翻译过来就直接要回滚了是吧?诶回滚日志它能够回滚行记录到某个特定的版本,用来保证事物的叫原子性和一致性。诶这呢,就提到我们另外的这三个特性了,对吧?诶那大家呢,首先看这个叫重做日志哈,诶说这个重做日它怎么也叫恢复提交这个事务修改页的一个操作呢,诶这里边就提到一个点,就是我们在这个呃一个事务当中呢,是不是会涉及到多个这个操作啊,多个比如说D操作,那么这个呢,我们去相应的操作过程当中,咱们修改的内容呢,是不是首先呢,是针对于内存层面,你加载过来的这个数据页当中,这个数据这呢,我们就做了这个修改了,对吧?那这个修改完以后的话呢,你注意咱们呢,还没有呢,是不是把这个数据呢,及时的去更新到这个磁盘中呢,对吧。诶,没有更新到这个磁盘中,而呢,真正我们把这个数据呢,更新到磁盘中了,这才算是不是达到了一个持久性的一个特征啊。对吧,这个大家应该清楚啊,如果你只更新内存呢,这不能叫持久性了啊,持久性呢,就相当于是我们即使出现呃数据库的这个故障啊,宕机等等,也不能改变我们这个数据呢,已经被修改的这个事实,你要光修改了内存了啊,一宕机磁盘中没修改,相当于呢,再一恢复的话呢,那刚才的事物呢,就没有了啊做的那些修改,诶那怎么办呢?诶我们为了保证呢,这个内存中的数据一定能够写入磁盘,咱们在这个内存中修改以后呢,咱们把这个数据呢,就记录到了一个叫诶readdo lock这样的一个日志当中。
02:29
然后确保呢,如果说我们出现这个宕机以后呢,呃,我们在恢复了这个MYSQL服务器之后呢,咱们也能够从这个日志文件里边呢,把这个数据呢,做一个恢复。诶,这个呢,就来保证我们这叫哎持久性。是吧,比较明显的就是恢复保证这个持久性,那其实呢,呃,你能让这个日志呢,相当于这个事务呢,一直执行完,呃,一直到最后的结束啊,其实呢,也一定程度上保证了它的一个一致性啊,这样的一个状态。行,那这个安杜lo呢,它就是主要呢,就做一个回滚了,哎,这个大家应该更清楚一些,对吧?啊,那这里边儿的话呢,其实就会涉及到啊,为了方便大家更好的理解呢,就涉及到了咱们在上一章呢,讲这个基础知识的时候呢,咱们提到过这个事物的这个状态啊,应该大家还有印象。
03:10
啊,就在这儿对吧,那么这个事物的状态呢,有两个最终的这个状态,要么呢就要提交的状态,就相当于我们这个数据呢,整个呢就确定下来了,啊这个事物说白了这几条电话操呢就执行成功了,要么呢,你就是一个终止的状态,相当于又回滚到这个最初的状态。而我们这个叫提交的状态呢,相当于呢,我们就是由这个叫A锐度日志呢来保障的。啊来保障的,然后呢,既然你已经提交了,那对数据库的修改呢,就是持久性的,那我们就要持久性的一个特征,那么这个时候呢,如果你执行到这个一半是吧,执行到这个一半这块呢,我们发现下边这个语句呢,执行失败了,那你要回滚到我们最初的这两个状态,哎,就是回到这个终止的这个状态,这个呢,我们就通过呢,叫安dolo诶这样的一个,诶回滚日志来进行一个保证的。哎,应该清楚是吧,哎这样的话一说呢,大家可能就更明确一些了,行,那我们再回过来。
04:01
啊说有的人呢,会认为说这个安度啊,就是这个锐度的一个逆过程啊,其实不然啊,为什么说叫逆过程呢?啊有的人他会这样的简单去说啊,说你这不就是一个事物中的几个操作吗?这个锐度呢,能保证的就是你一直往前突啊,一直往前冲,一直冲到这个事物呢提交,那就是这样,这就往前走的这样的过程,而这个安度的话呢,相当于是执行到一半呢,发现后边执行不了了,然后往回退啊就是一个呢是往前冲的,一个是往回退的,说这不就算是一个逆过程嘛,诶其实不要这样简单的去理解。啊,这样理解呢,其实是不对的啊,不对的,那么它们二者之间有什么联系和区别呢?来我们首先呢,做一个概述性的说明。首先呢,我们说这个锐度和安度呢,都被视作成一种叫恢复操作,这个大家理解吗。啊,安动的理解成恢复,大家可能更容易理解,因为呢,你把已经做的操作呢,在回滚回去,那就是一种恢复之前的这个数据的行为,对吧?而这个re动呢,也叫恢复啊,为什么呢?诶刚才其实也提到了,这是内存,这是我们这个磁盘,诶数据呢,你比如我们一秒钟以后,你才会去做这个刷盘的操作,那么在这一秒钟的时候呢,如果我们宕机了,诶咱们把这个数据呢,你的这个内存中的修改呢,我就记录到这个redo日志里边了,然后的话呢,你再重启服务器以后呢。
05:10
诶这个磁盘是吧,我们就从这个瑞度里边呢,做这个数据的一个恢复了,诶所以呢,这儿呢,它也是一种恢复的行为,对吧。好,那么他们两个呢?呃,还有什么联系和区别呢?呃,首先提到了他们二者呢,都是叫存储引擎这个层生成的这个日志,哎,都是存储引擎层生成日质,而我们后边讲的像这个blo啊,它就不是存储隐擎层了啊,那么它们俩的区别是什么呢?这个rilo啊,它是物理级别上的一个,哎,修改。啊,什么意思啊,就是它真正记录的就是我们在哪个页号上偏移量是多少,这个位置上写入了一个什么样的数据啊,就是针对我们实打实的物理磁盘上的这样的一个记录啊,这样一个记录,所以是物理级别上的,而这个安lo,安lo呢,它是一个逻辑上的操作。什么叫逻辑上操作啊,就咱们写那个测库语句,那不都是一个逻辑操作嘛,对吧,你比如说呢,我们针对一个表中的数据呢,做了一个insert行为啊,那么这个insert操作完以后啊,我们在安lo里边就会记录一个与之相反的叫做delete一个操作,那如果说你这个事物中的这个,诶要做回滚了,诶我们要把这条记录呢,是不是要删掉啊,哎,那我们就执行案度里边的一个delete就行了,所以它记录的是一些逻辑操作。
06:20
啊,这就是逻辑操作行,那么安度呢,呃,Log它的作用呢,除了我们说的叫事物的回滚之外呢,呃,还提到一个叫一致性非锁定读啊这个跟我们下下章要讲的这个MVCC呢,我们到时候呢去结合着来说。啊,这样行,那么整体上呢,大家先对这个锐度和安度呢,有一个整体上的一个理解,好,那下边的话呢,我们具体来看一看,这叫诶锐度日志。好,下面呢,咱们来讲解下这个瑞度日啊相关的这样的一些内容啊,这块首先我们来看啊,这个咱们讲这个诺D的时候呢,提到过说这个关于这个数据的这个存储和访问呢,咱们都是以这个页呢为最基本的单位的,对吧?当我们真正的要访问这个页面的时候呢,我们需要呢,把磁盘中这个数据呢,以页为单位呢,诶加载到我们这个内存中,放在这个叫B货铺里边。
07:05
诶,那么针对我们这个数据的这个增删改行为呢,我们也都是呢,先改咱们内存层面的这个数据,然后的话呢,咱们再以一定的频率呢,把这个数据呢,是不是更新到这个磁盘上。诶对吧,诶大家呢,清楚这个事儿,诶这呢我们稍微的说一下啊,就画一个简图,这个呢是我们内存中的这个数据,这个呢是我们这个,诶磁盘中的这个数据啊,那我们呢,针对内存中这个数据呢,我们做这个更新这个操作呢,是很快的啊,CPU跟内存打交道呢,这个速度相对来说来叫我们去更直接更新磁盘来讲要快很多,所以从这个意义上来讲呢,我们这个缓冲池呢,其实呢,就优化了CPU和磁盘之间的一个鸿沟,对吧?哎,我们中间呢,用它呢,在做了这样的一个优化的行为,好,那么我们对内存中这个数据呢,做了修改之后呢,我们接下来呢,会以一定的频率呢去更新到这个磁盘中。这里边提到了,首先你要更新,你要不更新,不更新的话呢,我们这个内存中的数据跟磁盘中数据就不一致了啊,而内存中的数据呢,我们说它是不稳定的是吧?诶一旦呢,断电以后呢,这就没有了,诶我们要保证这个事物的一个持久性啊,所以要保证呢,内存中的这个修改呢,诶磁盘中呢一定要体现,所以我们要去做这个刷盘的操作。
08:12
啊,要做这个刷盘操作,那么在你这个刷盘之前呢,诶,内存中这个做了修改,磁盘中没改这个呢,我们称为相应的这个数据呢,对应的这个页呢,就是脏页了。啊,就是内存中改了,磁盘中还没改呢,还没有同步呢,这时候呢,内存中这个叫脏印啊,这个先注意,然后的话呢,这里边提到说以一定的频率呢,我们去刷入这个磁盘,首先呢,对应的机制呢,我们叫check的机制啊,这个咱们后边会讲啊,那么为什么会以一定的频率呢,去刷新到这个磁盘中呢。啊,那很显然的话呢,你像我们这个内存中的数据刷新到磁盘本身呢,他们两个的介质不一样,呃,去写入磁盘的话呢,是不是本身呢就要慢一些,对吧?啊那这时候呢,你要是呃极其频繁的这种去做一个刷盘的操作的话呢,那首先呢,首先的话这个性能呢就会很差。啊,首先这个性能很差,呃,而且的话呢,我们刷盘的这个操作呢,你对应的这个页呢,它有可能是不是不是连续的这个页呢,啊是一些随机IO的行为,那这个性能呢,诶他也不会太好,对吧,先理解呢,我们这样的一个行为啊,这样的一个行为操作。
09:12
然后的话呢,我们来谈一谈这个瑞度之日呢,在整个这个过程当中,它充当了一个什么样的角色啊,为什么我们一定要去使用它,对吧?好,那这里边呢,我们要提到这样的一个问题啊,面对这样的一个现实,什么现实呢?诶还是回到我们刚才说的这个图哈,这个呢是内存,这个呢是我们这个磁盘。哎,这个磁盘好,哎,我在这块呢,在单独的画一个所谓的这个事物啊,这个事物里边的话呢,我们有几个呢,比如DML操作整个呢,这块构成了一个事物,那比如说我们这块,诶操作了一个啊这个。这个一个一个搜库语句了是吧,相应的我们对这个内存中这个数据啊做了一个修改,好我就记录一下,然后这块儿呢,我又操作了一个,我这块儿又做了一个修改,那么再往下操作的时候呢,诶我们发生了这个宕机行为了啊,相当于MYSQL服务器呢宕机了,那么宕机的话呢,这个时候的数据啊,我们这块呢,因为你也没提交,相当于这个事物呢,它就相当于没做啊我们真正这个磁盘中在这个我们这个MYS呢,在重启以后呢,其实呢,就是你这个15执行之前的这个状态。
10:09
那我们现在实际上是就能保证这种状态,就是这个状态下呢,不会涉及到这个刷盘的操作啊,我们内存中做了修改以后呢,呃,服务器宕机了,我们内存中这个数据呢,就没有了。啊,然后呢,再重启以后的话呢,呃,磁盘中的数据呢,是不是还是我们最初的那个数据,相当于我们什么也没做,从我们这个逻辑上操作上讲呢,也能讲得通,因为呢,你这个事物呢,是不是也没提交啊,没提交呢,就是最初的状态也是合理的满足我们的acid。这个是没问题的,那关键的就是在于我们这个事物呢,诶我换一个颜色啊,咱们这个事物的话呢,往下走走走走走走,我一直走到这儿做了一个可密的一个操作了。那你想此时呢,就意味着我们从逻辑层面呢,我这个事物已经结束了,而且还提交了对吧,那你这时候是不是也要满足这个a cid啊啊,那你就看我们内存层面呢,呃,这就一个两个三个四个,这四个事儿呢,就全做了,在内存里边呢,我们这个事物呢,确实是都完成了,呃,但是呢,咱们提到了,呃,你内存完成可不意味着我们这个数据呢,真正意义上完成了,我们需要把这个事物呢,数据呢,给它,是不是真正在磁盘中做修改才能叫一个持久性,对吧?那这时候呢,是不是就提到这个刷盘的这个行为了。
11:15
而刷盘这个行为呢,我们提到是不是有一定的频率去这个刷呀。诶一定的频率去刷,那么就有可能会出问题啊,你比如说呢,咱们这个刷新的这个行为呢,假设是一秒执行一次啊,那恰好的话呢,在我们内存这个执行完,诶我也commit了啊,内存中这个数据呢,我们一秒以后呢,就要刷新到这个磁盘了,那么在不到一秒的这个时间之内,诶,我们现在这个MYSQL服务器的宕机了。啊,有这样的可能性的,对吧,那此时呢,一旦宕机的时候呢,你想想我们内存啊,数据呢,是不是就都没了,你在重启服务器以后呢,内存中的数据没了,磁盘中的数据呢,还是以前的,而我们这里边儿事物呢,都说了提交了,我们是不是就不能够保证这个叫持久性啊。诶不能保证持久性,诶所以这块呢,首先我们说出现问题了,对吧?啊,那么另一方面呢,其实就提到了,既然你叫持久性,那你对这个数据库的这个修改呢,呃,不管你系统有没有发生崩溃,那都应该是改变了的啊,现在你保证不了了。
12:12
那怎么办呢?啊,那我们就得想这个具体的解决办法啊,那一个比较简单粗暴的一个办法是什么呢?啊,你刚才不是说了吗?哎,这个咱们还换成这个红色的吧。刚才不是说了嘛,说这个呢是内存中的,诶这个是磁盘中的啊,说呢咱们需要保证他们两个尽可能要一致的,那你就别这个一定的频率了,或者别一秒钟一次了,是不是说我们内存中数据一旦修改了,是不是马上我们就去更新磁盘中的数据啊。啊,就是实时的这样的去做这个修改啊,就像我们说这个内存中,我们诶这个事物中执行一条update的语句,其实这个执行update语句就是更新我们这个内存中的是吧?啊然后这个一更新呢,这个也马上去更新啊这块呢,再来一条数据啊,一更新这个内存中一改,这个也也马上去改。诶是不是这样的话呢,我们尽可能的去保证这个叫呃这个持久性的,你比如说你这块你提交了啊,这块呢,相当于结束了,我们这呢,也马上相当于是给他确定的,给他保存下来啊,就成这样的一个特征了,对吧,这样行不行呢?呃可以啊,但是呢,这里边呢,会有问题啊,什么问题呢,刚提到了。
13:12
修改量呢,与刷新磁盘这个工作量呢,严重不成比例啊,这种情况可能存在,你比如说呢,我们把这个数据呢,假设咱们只想改呃,某一个表当中某一条记录中的某一个字段啊,做一个极其微小的改变,可能呢只影响到一个字节。但是呢,我们前面讲过啊,这个数据呢,从磁盘读到内存中都是一页为单位的,那即使你只改这一个数据,咱们也需要呢,把这一个页呢,是不是加载到这个内存中。啊,这个我就这样翻翻一写啊,这内存中这一个页好呢,然后呢,你通过这个,呃,一个事物当中的一个update,一个update的语句,只改了这个页当中的一个字节。啊,然后呢,由于刚才我们说了,说内存中只要一改,是不是磁盘中也要改,那接下来的话,你是不是要把这个页的数据完整的啊,默认咱们说是16KB了,是不是要都刷新到我们这个磁盘上,你想这个成本是极高的,我们只改了一个字节,但是呢,我们这时候却需要呢,有16KB数据的一个刷盘的操作。
14:06
啊,一方面呢,这个呃,原来是一四节,现在是16KB,有一个这个呃数量大小上的一个对比,另外的话呢,我们这时候呢,可是做了一个呃不同的介质上的一个呃修改是吧,这个呢会更慢一些。啊,这个呢,就是很崩溃啊,就是成本的就是差距太大了啊嗯,再者的话呢,就是我们可能写一个update语句的时候啊,这是一个具体事物当中的我们一个update,比如说我们想修改一下员工表当中啊工资是5000的员工呢,把他们工资呢都改成是6000块钱,那么5000的这个员工呢,他在表中呢,就有可能是不是在不同的页中去存储的,那么你都加载到我们这个内存中去做了修改之后呢,咱们接着呢去刷新到磁盘中的时候呢,这些页可能不是连续的,那就意味着是随机IO,我们都得需要找到一个一个的页,那这个呢,随机IO呢,本身成本呢就也很高。对吧,诶这样两个原因诶导致呢,就我们实际上没有这样去选择啊,这个成本呢,实在是太高了啊行,那我们应该怎么去做呢,或者我们想怎么做会更好呢。
15:07
诶这里边呢,其实就提到了我们叫锐度啊这样个情况,咱们呢想实现的事儿啊,其实呢,挺简单的什么事啊,咱们只不过呢,就是希望什么呀,当我们这个事物提交以后,你内存中呢,肯定是改了,诶咱们希望呢,就是你内存中这个改了以后呢,这个磁盘中呢,也一定确定呢得能改啊,我们就呃说不想着说实时的去这样更新了,那怎么办呢?那我们就说呢,把你内存中这个修改的这个事儿啊,咱们先呢给你保存到一个文件里边。啊,这个文件呢,其实就是一个日志了啊,那么这个日志呢,诶,根据它的作用呢,我们就起了名,它这个名字呢,就叫做redo日志。就相当于把内存中这个修改呢,我们就直接呢,诶记录到这个日志文件里了,注意这是一个物理磁盘上真实存在的一个文件,好,那么呢,呃,当我们后边你不是一秒呢刷盘一次吗?刷盘一次刷盘一次这个这都正常,这都没事儿是吧?你这块呢,诶在这个刷盘之前呢,你这个内存中的数据呢,我们都是往这块呢先记录哈。
16:02
那一旦呢,说你这个一秒钟的这个数据呢,诶我们这个服务器的宕机了,呃,那这一秒钟的数据怎么办呢?诶服务器重启以后呢,由于呢,人家已经提交了这个失误了,内存中改了,然后我们这个呢,是不是日志文件也记录了,诶磁盘中还没改呢,我们在启动以后呢,是不是把这个re度日志中的这个数据呢?诶重新呢做一个恢复啊对我们磁盘中做一个修改,这不就保证了你之前的那个,诶commit的这个数据啊,在磁盘中呢,体现出来这个修改了。哎,保证了这个叫持久性。诶这呢就是我们锐度它的一个作用,我们这呢仍然可以考虑呢,比如说一秒诶去做一个刷盘的操作,诶我们就可以不变啊,那么这个弊端呢,咱们就也没有诶呈现出来是吧?哎,OK,行,那这呢,就咱们说的这个锐度日志的一个作用啊,那这里边我们提到的一个技术呢,叫wal的一个技术,叫right load。啊,Logging是吧,诶叫什么呀?叫这个日志优先写是吧?呃,Hadde就是优先写啊,或者叫优先写日志的一个,呃,技术啊,就是相当于呢,我们对内存中的这个数据啊,你做了这个更改之后呢,先不要想着去刷新到我们这个磁盘这个文件中啊先呢把它保存在这个日志当中。
17:12
然后呢,你再考虑呢,就是我们后续呢,这个需要,诶刷盘的时候,或者需要恢复的时候呢,诶再去使用,诶就是我们后续使用这个日日的这样一个情况啊,就一定要先把这个事儿呢往日日放。啊,诶,因为这个速度呢,其实是比较快的啊,这个速度是比较快的啊,这下边其实也就自然而然的就提到我们选择这种方式的这个优点是什么是吧?诶日的好处是什么?特点是什么啊第一个说它降低了我们刷盘的频率,诶就是相当于我们一开始这个简单粗暴这个方式来讲的话呢,诶那你实时刷我们这呢,是不是还可以维持一秒钟一刷,诶这个呢,是不是要更好一些,对吧?那其次的话呢,说这个瑞度日啊,它占用的这个空间还比较小,这也算是个优点。啊,虽然说我们那个内存中的数据呢,先把它保存在这个,呃,Redo log当中啊,说这个磁盘空间是不是占用会比较大啊,这块想要说的是呢,它占用空间呢很小啊,这也是它的一个优点啊。
18:01
优点好,那么它的特点是什么呢?就是瑞度之日啊,它是顺序写入磁盘的啊,就是我们把这个,呃,这个事物当中啊,你执行的每一个语句啊,产生的这个具体的操作,呃,我们是按照这个顺序呢,记录在我们这个锐度日志当中的啊,那它呢,其实也是对应的这个磁盘文件了,那它就相当于是顺序写入一个磁盘文件啊,顺序的IO比这个随机呢,它要快一些。啊,其次的话呢,这里边提到说事物它这个执行过程啊,这个redolog它是不断记录的啊,这是它的一个特点了,就。诶,那么这个特点呢,相较于我们后边要讲的这叫blog啊,它是有区别的啊blog咱们先泛泛说一下,咱们前面提到过这个叫主从复制啊,就是讲到这个我们,呃,数据库整个调的时候呢,呃,就是如果是你单台主机,呃,这个性能达到极限了,我们是不是可以使用这个相当于多台这个服务器是吧?诶我们可以呢,比如说简单来讲呢,就一台当主机,一台当这个从机,然后呢,这个主机呢来负责这个写的操作,诶然后这个从机呢来负责这个读的操作,那这时候你肯定要保证这个主从是不是数据的要一致性啊。
19:03
对吧,你这里边儿写入一个数据之后呢,那个从表中是不是也应该有这个数据,那这时候我们怎么保证呢?诶我们就提到了一个叫做bin log。哎,后边我们讲了这样一个日志啊,Blog日志,它这个二进制的日志,那么这个blog什么意思啊,就是我们主机当中呢,比如说你写过一条记录,我们就在blog里边呢,去做了一个记录,然后的话呢,我们从今呢,从那个blog日当中呢,把这个数据呢恢复过来,相当于你也加了一条记录。哎,就这样个情况啊,好,那大家会发现呢,说诶这个redolog怎么感觉跟那个blog好像作用一样呢。是吧,有点像哈,就是你这块呢,做了什么事,我们这呢都记录一下,那readlo呢,为了便于我们去做这个事物的一个持久化,你做什么了,是不是我们也记录一下,但是注意他们二者呢,还是有区别的,首先呢,是不同的日志啊,没有用一套日志去做啊,其次的话呢,我们说这个redolo呀,它是在存储引擎层产生的,而blog呢,是在数据层产生的。啊,我们针对一个事物假设呢,它有10万行这个插入这个行为,那么在这个过程当中,我们是不断的在往这个呃,Redo log中呢去写,就是你这个事物呢,执行的过程当中,我们就开始去往redolog里边做记录了,这个blog呢,不记录,当我们这个事物提交的时候呢,诶我们才会一次性的写入到我们这个blog文件当中,所以他们二者呢是有一个区别的。
20:14
啊,它不断的在记录啊,执行过程当中不断记录,行,那么具体来讲呢,我们这blog如何去使用呢?咱们到后边呢,讲到这个其他日志的时候呢,咱们再说行,那这样的话呢,咱们就把这个诶readlo呢,它的这个诶作用,还有它的这个好处是什么啊,咱们首先得明确出来。
我来说两句