《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 | 答疑文章(一):日志和索引相关问题-极客时间

  • 6
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值