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是固定大小的,由多个文件组成一个环形的结构,

image.png

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

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

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

sql 更新过程详解

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

image.png

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_commitsync_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 是否完整,完整则对还未提交的事务进行提交,不完整则回滚事务。

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

image.png

如上图所示,

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🐋 相关编程知识

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/537659.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring启动“--”设置参数没生效

现象 在idea中启动SpringBoot项目时,使用“--”设置的启动参数没有生效,如修改端口号“--server.port8082” 原因 排查发现是因为在使用SpringApplication.run启动项目时,没有将args参数传入run方法。 修复方案 SpringApplication.run参数中…

【Sql】MVCC有关问题,以及锁,日志和主从复制原理

目录 MVCC 解决什么问题? 实现原理 隐式字段 undo log Read View(读视图) InnoDB 对 MVCC 的实现 锁 分类 锁升级? InnoDB 的行锁? 死锁避免? 乐观锁和悲观锁 日志 主从复制原理 主从复制的作用 MySQL主从复制解决的问题 涉…

面试经典-16- 环形链表

题目 给你一个链表的头节点 head ,判断链表中是否有环。 如果链表中有某个节点,可以通过连续跟踪 next 指针再次到达,则链表中存在环。 为了表示给定链表中的环,评测系统内部使用整数 pos 来表示链表尾连接到链表中的位置&#…

基于springboot实现数据资产管理系统项目【项目源码+论文说明】计算机毕业设计

基于springboot实现数据资产管理系统演示 摘要 固定资产管理系统主要是完成对系统用户管理、资产信息管理、资产变更管理、资产用途管理、资产类别管理和资产增减管理。因为利用本系统管理员可以直接录入信息,修改信息,删除信息,并且若在录入…

vue3 el-form中嵌套el-tabale 对输入动态校验

简单案例 <el-form :model"Form" :rules"rules" ref"FormRef" class"formDiv"><el-table :data"Form.copyWriters" style"width: 100%"><el-table-column label"文案链接"><temp…

3、设计模式之工厂模式2(Factory)

一、什么是工厂模式 工厂模式属于创建型设计模式&#xff0c;它用于解耦对象的创建和使用。通常情况下&#xff0c;我们创建对象时需要使用new操作符&#xff0c;但是使用new操作符创建对象会使代码具有耦合性。工厂模式通过提供一个公共的接口&#xff0c;使得我们可以在不暴露…

论文阅读:Iterative Denoiser and Noise Estimator for Self-Supervised Image Denoising

这篇论文是发表在 2023 ICCV 上的一篇工作&#xff0c;主要介绍利用自监督学习进行降噪的。 Abstract 随着深度学习工具的兴起&#xff0c;越来越多的图像降噪模型对降噪的效果变得更好。然而&#xff0c;这种效果的巨大进步都严重依赖大量的高质量的数据对&#xff0c;这种对…

【数据结构】二叉树---AVL树的实现

目录 一. 什么是AVL树 二. AVL树的结点结构定义 三. AVL树的动态平衡法 1. 左单旋转 --- RL(RotateLeft) 型调整操作 2. 右单旋转 --- RR(RotateRight) 型调整操作 3. 先左后右双旋转 --- RLR (RotateLeftRight) 型调整操作 4. 先右后左双旋转 --- RRL (RotateRightL…

NBlog整合OSS图库

NBlog部署维护流程记录&#xff08;持续更新&#xff09;&#xff1a;https://blog.csdn.net/qq_43349112/article/details/136129806 由于项目是fork的&#xff0c;所以我本身并不清楚哪里使用了图床&#xff0c;因此下面就是我熟悉项目期间边做边调整的。 目前已经调整的功能…

FFmpeg——开源的开源的跨平台音视频处理框架简介

引言&#xff1a; FFmpeg是一个开源的跨平台音视频处理框架&#xff0c;可以处理多种音视频格式。它由Fabrice Bellard于2000年创建&#xff0c;最初是一个只包括解码器的项目。后来&#xff0c;很多开发者参与其中&#xff0c;为FFmpeg增加了多种新的功能&#xff0c;例如编码…

【Node.js从基础到高级运用】十一、构建RESTful API

在本篇博客中&#xff0c;我们将综合之前讨论的内容&#xff0c;深入探索如何使用Node.js构建一个RESTful API。我们将重点讨论设计合理的API端点&#xff0c;展示如何通过代码实现这些端点&#xff0c;并指导如何使用Postman测试我们的API&#xff0c;确保其按预期工作。 前提…

python爬虫(9)之requests模块

1、获取动态加载的数据 1、在开发者工具中查看动态数据 找到csdn的门户的开发者工具后到这一页面。 2、加载代码 import requests headers {User-Agent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36…