当前位置: 首页 > 科技观察

你是否对Redolog和Binlog感到困惑?

时间:2023-03-18 00:51:19 科技观察

本文转载自微信公众号《Java极客技术》,作者鸭血范。转载本文请联系Java极客技术公众号.阿芬这么贴心,我肯定跟你解释清楚了~在MySQL中,尤其是存储引擎使用InnoDB的时候,肯定有两个绕不过去的概念:redolog(重做日志)和binlog(二进制日志)。er说:redolog是InnoDB存储引擎层的日志,所以如果你用的存储引擎不是InnoDB,那就没得说了redologbinlog是MySQLServer层记录的日志,所以不管什么存储引擎用的,只要是MySQL的,都会有binlog。在做MySQL主从复制的时候,会用到binlog。那么,你有什么问题吗?为什么我们有redolog和binlog,只有一个log不能用?让我们进入细节让我们看看他们做了什么。为什么我们需要重做日志?我们可以这样想。如果没有redolog,MySQL查询如何进行呢?说的还行,毕竟只是查询记录,并没有改变数据。添加和更新操作呢?现在来了一个update语句,后面会不会有一定的限制条件,比如现在要更新一条记录,把A的银行卡余额更新为1k,这个语句是不是要来一个限制条件,类似于whereuserName='A',就是说一般的update操作都是伴随着query操作的,你得先找到这个人,然后再进行update操作对吧?如果数据量比较小,很快就能找到并更新,但是如果数据量比较大,里面有1亿条数据,怎么办?而且更新操作必须写到磁盘,那么中间的IO成本怎么算呢?如果我有几十条更新语句一个接一个更新呢?如果这样想,你可以认为这些操作的成本很高。你能减少这些成本吗?这就是重做日志的作用。当一条记录更新时,InnoDB引擎会先将这条记录写入redolog,同时更新内存,所以即使这条数据更新成功了,但是此时,还没有更新到磁盘,对吗?不用担心,InnoDB会在合适的时候把这种更新记录到磁盘的想法或者技术有个专有名词:WAL技术,也就是WriteAheadLogging。核心是先写日志,再写磁盘。这里有一个问题。重做日志不能一直写吗?如果更新了Hold如果操作已经写入redolog,如果不限制大小,服务器上的存储空间可能会被redolog占满,所以InnoDB的redolog是固定大小的。比如我们配置一组4个文件,每个文件的大小为1GB,那么它的操作可能是这样的:可以看到,主要是写pos和checkpoint,写pos比较容易理解,就是当前记录位置,需要记录的操作从当前位置向后移动,写入ib_logfile_3后,回到ib_logfile_0开头继续写入checkpoint,也就是当前要擦除的位置,即InnoDB引擎不会在正确的时间持久化这些操作并将它们更新到磁盘。转换后的数据可以被删除吗?writepos和checkpoint之间的部分是可以用来记录操作的部分,那么如果writepos和checkpoint相遇了怎么办?是不是意味着此时分配的redologsize用完了,此时不能再进行update操作了。必须停下来,把关卡往前推。正是因为有了redolog,InnoDB才能保证即使数据库异常重启也无所谓,之前提交的记录还在,只需要根据redolog中的记录恢复即可。所以熟悉DBA的可以问问我们的MySQL半个月内能不能恢复到任意日期。秒,如果对方回答是,不要怀疑,他真的不是在吹嘘binlogbinlog是MySQLServer层的日志,我们就拿这个举例。在谈之前,我们需要了解一下redolog和binlog的区别:redolog是InnoDB引擎特有的,而binlog是MySQL的server层实现的。所有引擎都可用。redolog是物理日志,记录“XXX页上进行的XXX修改”;binlog是逻辑日志,比如“id=2的行的c字段加1”redolog是固定大小的,所以它的空间会被用完。如果用完了,有些操作必须先写入磁盘再继续;binlog是可以追加写入的,即binlog没有空间的概念,一直写入即可。了解了它们的区别之后,我们以更新操作为例。现在我想在行id=2的c字段中添加1,它在MySQL级别是如何实现的?首先会找到id=2的数据,然后找到c字段加1。此时引擎会将这行数据更新到内存中,同时在redo中记录这次更新操作日志。此时redolog处于prepare状态。然后executor生成本次操作的binlog,并将binlog写入磁盘。执行者调用引擎的提交事务接口后,引擎将刚刚写入的导入的重做日志从准备状态变为提交状态,从而将更新操作视为两阶段提交。在上面的描述中可以发现redolog其实先是prepare状态,binlog写入后才进入commit状态。第一种方法称为“两阶段提交”。为什么会有这样的方法呢?redolog和binlog都可以用来表示事务的提交状态,两阶段提交就是为了让两种状态在逻辑上保持一致。假设,如果不使用这种方式,而是先写redolog,再写binlog呢?如果写binlog时出现异常,说明update操作已经进入redolog,但是此时binlog还没有更新。是否存在数据不一致?先写binlog再写redolog也是这个道理。所以写的时候,先让redolog处于prepare状态,binlog写完后,再让redolog处于commit状态,这样才能保持逻辑上的一致,非常感谢阅读~