MYSQL 是如何保证binlog 和redo log同时提交的?
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服务锁定的数据资源。
通过两阶段提交,来查看业务的最终一致性。
最后,
自荐一波:
欢迎朋友们关注我的公众号:【蓝胖子的编程梦】!
学习容器知识,性能监控,Golang 相关编程知识
MYSQL 是如何保证binlog 和redo log同时提交的?的更多相关文章
- binlog和redo log日志提交
组提交(group commit)是MYSQL处理日志的一种优化方式,主要为了解决写日志时频繁刷磁盘的问题.组提交伴随着MYSQL的发展不断优化,从最初只支持redo log 组提交,到目前5.6官方 ...
- MySQL中的重做日志(redo log),回滚日志(undo log),以及二进制日志(binlog)的简单总结
MySQL中有六种日志文件,分别是:重做日志(redo log).回滚日志(undo log).二进制日志(binlog).错误日志(errorlog).慢查询日志(slow query log).一 ...
- MySQL:binlog 和 redo log
[参考文章]:MySQL中Redo与Binlog顺序一致性问题? [参考文章]:极客时间 1. 数据更新时的日志处理流程 1.1 redo log(prepare状态) 此时SQL已经成功执行了,已经 ...
- 必须了解的mysql三大日志-binlog、redo log和undo log
日志是 mysql 数据库的重要组成部分,记录着数据库运行期间各种状态信息.mysql日志主要包括错误日志.查询日志.慢查询日志.事务日志.二进制日志几大类.作为开发,我们重点需要关注的是二进制日志( ...
- 3000帧动画图解MySQL为什么需要binlog、redo log和undo log
全文建立在MySQL的存储引擎为InnoDB的基础上 先看一条SQL如何入库的: 这是一条很简单的更新SQL,从MySQL服务端接收到SQL到落盘,先后经过了MySQL Server层和InnoDB存 ...
- 技术分析 | 通过DML语句浅谈binlog和redo log
欢迎来到 GreatSQL社区分享的MySQL技术文章,如有疑问或想学习的内容,可以在下方评论区留言,看到后会进行解答 GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. 1 ...
- 数据库日志——binlog、redo log、undo log扫盲
日志是数据库中比较重要的组成部分,很多核心的功能必须依靠日志才能完成. 该篇文章简要介绍了binlog.redo log与undo log,能够在一定程度上拓宽对mysql日志的整体认识. binlo ...
- MySQL的两种日志类型,redo log,binlog
文章内容学习:极客时间-林晓彬老师-MySQL实战45讲 整理而得 我们知道MySQL数据库在发生意外宕机的情况下,可以将数据恢复到历史的某个时间点,能实现这个功能依靠的是日志,MySQL提供两种类型 ...
- binlog、redo log、undo log区别
root@(none) 04:17:18>show variables like 'innodb_log_group_home_dir';+--------------------------- ...
- MySQL是怎么保证redo log和binlog是完整的?
摘要:WAL机制保证只要redo log和binlog保证持久化到磁盘,就能确保MySQL异常重启后,数据可以恢复. 本文分享自华为云社区<MySQL会丢数据吗?>,作者: JavaEdg ...
随机推荐
- 【C语言深度解剖】复数运算问题--【好题系列】学会这题,结构体没问题
复数问题 今天博主给大家带来一道博主自己在学校做到的一个题目.这个题目可以很好的加深我们对C语言结构体的理解,在这里分享给大家.学懂这题,我们的C语言结构体,没问题了! 本篇建议收藏后食用!以免退出找 ...
- Mygin之错误恢复Recover中间件
本篇是mygin这个系列的最后一篇.如果想自己动手实现一个类似Gin的Web框架,建议从 mgin第一篇开始, 总代码行数有效行数只有600多行 github源码 mygin 目的 实现错误处理机制 ...
- ElasticSearch7.3学习(七)----Mapping映射入门
1.mapping映射 概念:自动或手动为index中的_doc建立的一种数据结构和相关配置,简称为mapping映射.插入几条数据,让es自动为我们建立一个索引 PUT /website/_doc/ ...
- 21.1 动态TLS--《Windows核心编程》
应用程序通过调用一组4个函数来使用动态 TLS,这些函数实际上最经常为 DLL 所使用. 通常情况下,如果DLL使用 TLS,那么当它用 DLL_PROCESS_ATTACH 标志调用它的 DllMa ...
- Python内置小工具(非常实用!)
一.1秒钟启动一个下载服务器在工作中时不时会有这样的一个需求:将服务器(或者自己电脑)上的文件传给其他同事.将文件传给同事本身并不是一个很繁琐的工作,现在的聊天工具一般都支持文件传输.但是,如果需要传 ...
- UVA12655 Trucks 题解
题目传送门 前言 中文题目可以看 link . 前置知识 Kruskal 重构树 | 最近公共祖先 简化题意 给定一个 \(N\) 个点 \(M\) 条边的有向图,共有 \(S\) 次询问,每次询问从 ...
- C#后端接收前端的参数
接收参数 1. 直接使用 [FromBody] 特性来告诉 ASP.NET Core 将请求的 JSON 数据反序列化为 实体类 对象 [FromBody] BlogNewsDTO实体类 点击查看代码 ...
- Linux 中iostat 命令详解
iostat命令详解 iostat 主要是统计 磁盘活动情况. iostat有以下缺陷: iostat的输出结果大多数是一段时间内的平均值,因此难以反映峰值情况iostat仅能对系统整体情况进行分析汇 ...
- 【OpenGL ES】正方形图片贴到圆形上
1 前言 纹理贴图 中介绍了将矩形图片贴到矩形模型上,本文将介绍:在不裁剪图片的情况下,将正方形的图片贴到圆形模型上. 思考:实数区间 [0, 1] 与 [0, 2] 的元素可以建立一一映射关 ...
- zabbix-server.service failed解决方法
1.问题描述 centos7中安装的zabbix server在重启系统后无法启动了,查看状态报错如下: 2.问题原因 selinux没有关闭! 3.解决 永久关闭selinux, 将SELINUX值 ...