MySQL 是如何保证 binlog 和 redo log同时提交的?

IT科技2025-11-05 04:21:52434

MYSQL 一个事务在提交的何和时候能够保证binlog和redo log是同时提交的,并且能在宕机恢复后保持binlog 和redo log的保证一致性。

先来看看什么是同时提交redo log 和binlog,以及为什么要保持它们的何和一致性。

什么是保证redo log,binlog

redo log是同时提交innodb引擎层产生的日志, MYSQL从磁盘读取数据的单位是一页,当修改页中某条数据时,何和该行所在的保证数据页就变成了脏页,由于脏页并不会立马刷新到磁盘,同时提交所以redo log会记录下数据页进行了哪些变动,何和用于服务崩溃时的数据恢复。redo log是保证固定大小的,由多个文件组成一个环形的同时提交结构。

图片

redo log由两个指针,何和write pos 和checkpoint,保证都是同时提交顺时针移动,write pos 记录redo log当前写入的位置,服务器租用  checkpoint往前移动,就代表就移动过的redo log记录的脏页刷新到磁盘上。所以,write pos 和checkpoint 之间的位置就代表redo log 还可以写的空间大小,当write pos等于checkpoint时,MYSQL则必须等待脏页刷新完毕后才能继续进行修改操作。

binlog 是mysql server服务层产生的日志。两者的用途也不一样。binlog 则主要用于数据库的备份,主从同步。binlog记录的是行变化,记录格式也有3种,statement,row,mixed,这里就不细讲了。

在了解了redo log 和binlog的含义和各自的作用后,我们先来看看它们在一次sql更新中是如何运作的。

sql 更新过程详解

来看下在一次事务过程中,免费信息发布网它们的工作机制。假设我们在进行修改操作,那么可以用下面的流程图来表示:

图片

1,首先判断要修改的数据是否在内存里,没有的话就从磁盘读取到内存。

2,写入redo log,注意这里写入的redo log仅仅是prepare状态,只有等到正式提交的时候才会变成commit状态。并且写入redo log也不是直接落盘,其实是写入到了redo log buffer 中,落盘时机受到innodb_flush_log_at_trx_commit 参数控制。

MYSQL会有一个后台线程,定时刷新redo log buffer 中的数据到磁盘上。除此以外,当innodb_flush_log_at_trx_commit 值为1时 redo log则会在在prepare阶段将redo log buffer 中的数据落入磁盘。

注意,这里说的事务提交的时候redo log buffer中的数据刷到磁盘上,网站模板并不仅仅是执行的当前事务,比如A,B两个事务,A事务执行到一半,写了部分数据到redo log buffer,那么B此时提交事务,同样也会将A事务的redo log 刷到磁盘上。

当innodb_flush_log_at_trx_commit 值为 0 时,redo log buffer则不会在prepare或者事务提交时刷盘,而是由后台定时任务定时刷新redo log buffer中的数据到磁盘上。

当innodb_flush_log_at_trx_commit 值为2时,则是将redo log buffer中的内容刷新到文件系统缓存中,由操作系统决定何时刷新到磁盘上。

所以可以看到,在事务执行过程中,redo log是可能一部分在内存,一部分已经落入磁盘了。

3, 在写完redo log后,会去写binlog,写binlog同样不是直接写文件,而是写到binlog cache中,那么binlog是何时刷新到磁盘上呢,这个是由sync_bin参数决定的。

sync_binlog = 0 :提交事务时,将内存中的binlog cache写到文件系统缓存中,后续交由操作系统决定何时将数据持久化到磁盘。sync_binlog = 1 :提交事务时,将binlog cache中的数据写入到文件系统缓存,并立马刷新到磁盘。sync_binlog =N(N>1) :提交事务时,都写到文件系统缓存,但累积 N 个事务后才 fsync 刷新到磁盘。

4, 最后一步便是对事物进行提交,按参数设置分别对redo log和binlog进行落盘处理。

为什么要保证binlog 和redo log 同时提交

看完了整个sql更新过程,先说下结论,将innodb_flush_log_at_trx_commit 和 sync_binlog都设置为1  能够保证binlog 和redo log 同时提交。

再来看看如果redo log和binlog不同时提交会导致什么问题❓

redo log和binlog不同时提交会导致主备不一致

如果在一个事务提交过程中, binlog写入成功了,此时主库宕机,redo log写入失败,主库恢复后,那么binlog可能就会被从库拿去执行,然而主库的redo log是没有修改数据的,所以造成主备不一致。

换过来,redo log写入成功,但是binlog提交失败,从库就会缺失新的修改数据,造成主备不一致。

两阶段提交避免数据不一致

接着,我们来细聊 MYSQL在上述sql更新过程中,是如何保证redo log和binlog是同时提交的。

上述事务执行过程中,可以看到对于redo log的提交分了两个阶段,第一个是redo log的prepare 阶段,第二个是commit阶段。

宕机恢复时,redo log执行恢复的逻辑概括如下:

1,只要redo log变成了commit状态,MYSQL就认为事务是成功了。

2,而恢复时,发现redo log是prepare 状态的话,就会去判断对应事务的binlog 是否完整,完整则对还未提交的事务进行提交,不完整则回滚事务。

我们来分析下异常的情况:

图片

如上图所示:

1,在第一种异常情况下,redo log 和binlog都没有写入,主备是一致的。

2,第二和第三种异常情况, redo log已经落入磁盘,最后就看binlog是否完整了,完整宕机恢复后进行事务提交,备库即使得到binlog,也能保证与主库恢复后事务提交的数据 保持一致。

📢📢📢需要注意的是,innodb_flush_log_at_trx_commit 为1时才能保证redo log是在binlog写入前是已经落盘的,如果是0或者2,则有可能出现节点崩溃时,redo log没有写入到磁盘而丢失,而binlog是完整的情况,造成主备不一致。

两阶段提交带给业务开发上的思考🤔

从MYSQL 实现两阶段提交的逻辑,可以归纳下,它是如何做到对两个业务做到最终一致的。

我举个业务上的例子,  比如有A,B两个服务,A服务依赖B服务,如何保证在A服务上的数据操作和请求B服务接口这两个动作同时成功或失败❓

我直接说下结论:

借鉴两阶段提交的逻辑,我们可以将A服务的数据操作在业务设计上增加一个预扣减的概念,先锁定A服务数据资源,然后去请求B服务的接口,失败的话,则释放A服务锁定的数据资源,成功的话则进行真实的扣减。

除此以外,还需要增加一个对A服务数据进行补偿修复的定时任务,类似与MYSQL数据库宕机根据binlog是否完整看事务是否提交一样,定时任务定期查看还没有终结的A服务数据,拎出来请求B服务查看业务成功状态,B服务返回成功,则将A服务的业务数据进行真实扣减,否则释放A服务锁定的数据资源。

通过两阶段提交,来查看业务的最终一致性。

本文地址:http://www.bzuk.cn/news/002e9299905.html
版权声明

本文仅代表作者观点,不代表本站立场。
本文系作者授权发表,未经许可,不得转载。

全站热门

如何利用电脑表格进行打印?(一步步教你掌握新手电脑表格打印技巧)

4、待所有域名查询结束后可在右侧点击导出结果,即可以excel的文件方式将查询到的结果导出。

2. 不要花大价钱买域名,新手鉴别能力不足,容易投资失误。

主流搜索引擎显示的相关搜索项越多,越能积极反映该域名的市场价值。同时,被评估域名的搜索引擎显示结果不佳可能是由于以下两个原因:

手机连接电脑时发生未知错误的解决方法(解决手机连接电脑出现问题的简易步骤)

2、定期提交和投标域名注册。例如,益华网络点击“立即预订”后,平台会抢先为客户注册域名。当然,一个域名可能会被多个客户预订,所以出价最高的人中标。

域名不仅仅是一个简单的网站。对于有长远眼光的公司来说,在运营网站之前确定一个优秀的域名对有长远眼光的公司来说是非常重要的。这对今后的市场营销、产品营销和企业品牌建设都具有十分重要的意义。优秀的域名是企业在市场竞争中获得持久优势的利器。

Status、Creation Date、Expiration Date

友情链接

滇ICP备2023006006号-33