• 《MySQL实战45讲》——学习笔记15 “redo log与bin log答疑“总结【建议收藏】


    前文《MySQL实战45讲》——学习笔记01-03 “MySQL基本架构、日志系统、事务隔离“介绍了MySQL的日志系统,包括redo log和bin log以及两阶段提交,本篇作为该内容的补充,进一步解释MySQL中的这两套日志的关系;

    问题1:为什么要搞2套日志?

    1. redolog只有InnoDB有,别的引擎没有;

    2. redolog是循环写的,历史已执行的会被覆盖,不全量持久保存,因此binlog的“归档”这个功能,redolog是不具备的;

    问题2:binlog与redolog区别?

    1. redolog是InnoDB引擎特有的;binlog是MySQL的Server层实现的,所有引擎都可以使用;

    2. redolog是物理日志,记录的是“在某个数据页上做了什么修改”;binlog是逻辑日志,记录的是这个语句的原始逻辑,比如“给ID=2这一行的c字段加1”;

    3. redolog是循环写的,空间固定会用完;binlog是可以追加写入的,即文件写到一定大小后会切换到下一个文件,历史日志不会被覆盖;

    问题3:什么是两阶段提交?

    先看[执行器](绿色)与[InnoDB引擎](红色)是如何更新一条指定的数据的:

    可见,redolog的写入拆成了两个步骤:prepare和commit,这就是"两阶段提交";

    问题4:不引入两个日志,也就没有两阶段提交的必要了;只用binlog来支持崩溃恢复,又能支持归档,是否可以?

    不可以;binlog不具备崩溃恢复crash-safe能力,没法做数据的恢复;因为:

    首先要清楚,InnoDB引擎使用的是WAL技术,执行事务的时候,写完内存和日志,事务就算完成了;内存中的脏页会有后台任务根据一些机制刷入磁盘;

    如果发生崩溃,要依赖于日志来恢复数据页;但是,binlog没法用来恢复内存中的数据页;

    (1)第一点,binlog是逻辑日志,记录的是这个语句的原始逻辑,不能直接应用于内存
    (2)第二点,重放binlog的时候,你不知道哪些日志对应的修改已经写入磁盘,也就是虽然binlog拥有全量的日志,但没有一个标志让innoDB判断哪些数据已经刷盘,哪些数据还没有

    恰恰以上两点,redolog都具备,

    (1)第一点,redolog是物理日志,记录的是“在某个数据页上做了什么修改”,可以用来恢复内存;
    (2)第二点,redolog的循环写特性就天然的具备"判断对数据的修改是否落盘"的标志——已经刷入磁盘的数据都会从redolog删除(checkpoint移动);

    你可能会想,优化一下binlog的内容,让它来记录数据页的更改可以吗?但,这其实就是又做了一个redolog出来;至少现在的binlog能力,还不能支持崩溃恢复;

    问题5:那能不能反过来,只用redolog,不要binlog?

    如果只从崩溃恢复的角度来讲是可以的;你可以把binlog关掉,这样就没有两阶段提交了,但系统依然是crash-safe的;

    但是,如果你了解一下业界各个公司的使用场景的话,就会发现在正式的生产库上,binlog都是开着的;因为binlog有着redolog无法替代的功能;

    (1)redolog不能用来归档;redolog是循环写,写到末尾是要回到开头继续写的;这样历史日志没法保留,redolog也就起不到归档的作用;

    (2)MySQL系统依赖于binlog;binlog作为MySQL一开始就有的功能,被用在了很多地方;其中,MySQL系统高可用的基础,就是binlog复制;还有很多公司有异构系统(比如一些数据分析系统),这些系统就靠消费MySQL的binlog来更新自己的数据;关掉binlog的话,这些下游系统就没法输入了;

    总之,由于现在包括MySQL高可用在内的很多系统机制都依赖于binlog,所以“鸠占鹊巢”redolog还做不到;

    问题6:redolog和binlog是怎么关联起来的?

    它们有一个共同的数据字段,叫XID;在写入redolog时,会顺便记录XID,即当前事务id;在写入binlog时,也会写入XID;

    问题7:在两阶段提交的情况下,是怎么实现崩溃恢复的呢?

    基于问题6,可知:二者通过XID就关联起来了;崩溃恢复的情况:

    (1)如果在写入redolog之前崩溃,那么此时redolog与binlog中都没有,是一致的情况,崩溃也无所谓;

    (2)如果在写入redolog prepare阶段后立马崩溃,之后会在崩恢复时,由于redolog没有被标记为commit,于是拿着redolog中的XID去binlog中查找,此时肯定是找不到的,那么执行回滚操作;

    (3)如果在写入binlog后立马崩溃,在恢复时,由redolog中的XID可以找到对应的binlog,这个时候直接提交即可;

    问题8:处于prepare阶段的redolog加上完整binlog,重启就能恢复,MySQL为什么要这么设计?

    问题主要是跟数据与备份的一致性有关

    如果binlog写完以后MySQL发生崩溃,这时候binlog已经写入了,之后就会被从库(或者用这个binlog恢复出来的库)使用;

    所以,在主库上也要提交这个事务;采用这个策略,主库和备库的数据就保证了一致性;

    问题9:分布式事务也有"两阶段提交"的解决方案;怎么理解MYSQL中的"两阶段提交"?

    两阶段提交是经典的分布式系统问题,并不是MySQL独有的;

    redolog是在Innodb引擎内操作的,而binlog是在server层操作的,我们就可以把引擎层和server层看成两个分布式服务,那他们要分别进行两个相关联的操作,就意味着要实现分布式事务,而两阶段提交,就是其中的一种解决方案;

    因为这两个日志属于MYSQL的不同层,因此还是会存在一个成功一个失败的情况,就像分布式事务中不同分布式系统操作的数据源不同,并且可靠性也不同,就一定需要考虑A成功B失败的情况;

    有个前提——对于InnoDB引擎来说,如果redolog提交完成了,事务就不能回滚(如果这都commit了还允许回滚,就可能覆盖掉别的事务的更新);

    因此,如果不用两阶段,redolog直接提交,然后binlog写入的时候失败,这种情况下InnoDB又回滚不了,那结果就是主库数据和binlog日志又不一致了,肯定是不行的,最起码的问题就是主从就不一致了;

    两阶段提交也可以理解成给每个系统一个确认的机会,当每个人都说“我ok”的时候,再一起提交,如果前置就发现某个系统还没准备好时,就不用提交了;

    下篇文章:《MySQL实战45讲》——学习笔记16 “order by排序原理、varchar(255)“

    本章参考:15 | 答疑文章(一):日志和索引相关问题-极客时间

  • 相关阅读:
    wifi分销大师小程序v4.0.5独立版saas系统源码+前端
    七、HDFS文件系统的存储原理
    Aspose.Cells for Python via .NET crack
    文件系统管理--文件系统常用命令—挂载命令
    HJ3 明明的随机数
    这篇文章告诉你视频配音制作的方法
    MapStruct入门使用
    ui设计师简历自我评价的范文(合集)
    二分查找--C++实现
    PLC信号发生器(余弦信号)
  • 原文地址:https://blog.csdn.net/minghao0508/article/details/127763412