请你来了解一下Mysql-InnoDB中事务的两段式提交

欢迎订阅专栏,了解更多Mysql的硬核知识点,原创不易,求打赏

ACID:事务的四个特性

A:原子性

原子性表示把一个事务中所有的操作视为一个整体,要么全部成功,要么全部失败,是事务模型区别文件系统的重要特征之一

C:一致性

官方对一致性的解释为事务将数据库从一种状态转变为下一种一致性状态,在事务开始之前和食物结束以后,数据库的完整性约束没有被破坏。

而我对一致性的理解为事务的执行可以让各方在指定规则下都认可这个事务产生的变更。比如事务提交后将数据写入binlog,事务提交后redo会写入prepare,commit状态的数据,undo会维护该版本的数据,数据写入(聚集,非聚集)索引表等等。

就好像DDD中的限界上下文一样,大家对于这个领域的边界有共同且明确的认知

InnoDB事务的两段式提交中,主要就是对原子性和一致性的保证。

I:隔离性

隔离性基本的理解是事务之间不会互相干扰。但这是结果。通过什么方式可以使得事务的执行不会互相干扰呢?

如果数据库只允许串行化执行事务,那么就没有隔离性什么事,但是现在的社会,连人类都得加班,互卷,为了让自己的业绩,考核能够更好。对于数据库来说,不可能让一个数据库慢慢悠悠的执行事务,支持并发事务执行是必须的也是基本的职能(功能)。

因此系统必须支持事务的并发执行,事务的并发执行为了保证“线程安全”,必须通过一些手段让其操作在一定的限界内,不能让它们逾越法则。

所以就有了并发控制,锁的出现,通过并发控制,可以让相应的可读数据划分边界,对于不可读的内容做了屏蔽。通过锁,可以让对于同样数据的多个并发修改得以强制性串行执行。

D:持久性

需要注意的是持久性并不能保证机器物理级别的损坏(包括很多方便)或者山崩地裂导致服务器沉入大海后还要做数据恢复。针对这种情况还需要一些高可用的架构来辅助完成。

持久性保证的除了上面说的几种情况外,只要事务单方面确认提交了,那么就能够通过一些手段来恢复。

事务提交的过程图

d8d0f363cbb94d33b51661d48215b082.png

过程解释

其两段式提交主要就是在redo.log的两次prepare状态和commit状态。但是记住,并不是只有最后commit状态写入了才能恢复

假如redo.log中写入了prepare状态的数据,并且bin.log也写入了。但是写redo.log的commit状态的数据时丢失了,这时候还是可以恢复的。(那为什么不能只根据bin.log是否写入来判断事务成功,为什么还要有一个redo.log来增加复杂度呢?

因为bin.log太大了,如果系统恢复是通过bin.log来恢复,首先功能是没问题的,但是恢复的时间会很长。而redo.log很小啊(默认情况下只有48M),只需要遍历redo.log里面的数据,如果是commit状态的那么直接恢复。如果是prepare状态的,那么看一下bin.log有没有,有就恢复,没有就不恢复。

事务执行的效率

事务执行的效率除了受限于事务的大小等因素以外,还受限于磁盘的性能,为什么这么说呢?

因为默认情况下,每次都必须等到数据写入磁盘才表示事务提交成功,要不然中间如果出现问题,导致数据并没有写入redo.log或者bin.log,直接返回状态,那么必然有数据不一致性问题。

innodb控制这个过程是通过innodb_flush_log_at_trx_commit参数控制的。

0:每次事务提交的内容不写入文件,而是由master thread进行。master thread中每秒都会执行一次fsync操作

1(默认值)每次事务提交的内容必须执行一次fsync刷到磁盘,才会标记事务为成功。

2:每次事务提交的内容只写入文件系统的缓存,不进行fsync操作。

文件系统的缓存中数据写入文件几乎依赖的是操作系统的一些机制了

  • 脏数据回写策略:当文件系统缓存中的数据被修改后,会被标记为"脏"数据(dirty data)。文件系统会定期或在内存压力紧张的情况下(内核调度策略),将这些"脏"数据异步写入文件。

  • 超过内核参数设置的阈值:Linux内核有一些参数可以控制文件系统的回写行为,例如dirty_ratiodirty_background_ratio。当"脏"数据占用内存的比例超过dirty_ratio或超过dirty_background_ratio时,内核会触发异步回写操作。

  • 内核定期回写:内核中有一个脏数据回写线程 (pdflush 或 bdflush),它会定期(默认30秒)检查文件系统的缓存,将脏数据异步写入文件。

需要注意的是master thread执行fsync是固定有的功能,和事务本身的fsync并不互斥的。也就是说有时候不等本事物执行fsync,就已经让master执行了,并且master thread是每个表空间特有的线程,因此如果某个表有单独的表空间,那么其事务提交就完全靠它自己了

无论是0还是2,都不具备事务特性中的一致性,因为数据的提交变的不可预知

bin.log和redo.log的数据顺序一致吗?

那有一个问题了,bin.log和redo.log的写入顺序是不是就是一致的呢?是不是下面的这种呢

d80504382b514ec8beeec5a53dad4377.png

其实并不是,因为bin.log的写入是在事务完成后一次性写入的,而redo.log可能在事务执行过程中不断地写入

有可能是下面的这种顺序

c870084d5c10453f90557ad422510ce3.png

bin.log和redo.log 的数据格式一样吗? 

bin.log全程是binary log,记录的是对应的sql语句,是一个二进制文件

redo.log是一个物理格式数据,记录的是对每一个页的修改

延伸

redo.log的结构

redo.log的大小默认是48M,并且是由一个个redo log block组成的。一个redo log block的大小是512字节,所以默认情况下总有48MB / 512B = 98304个redo log block。

有没有发现redo log block的512字节的大小和磁盘扇区的大小是一样的,所以对于redo log block来说是可以保证原子性的,不需要doublewrite技术

5102ec1351ed4e8e9afcf1217a3d4970.png

一个redo log block最多可以存储492字节的数据,如果超过了492字节,就会被分配到下一个redo log block。那如果有多条日志都很小,比如10个字节,那么一个redo log block会包含多条日志,那怎么区分每个日志的初始位置呢?

通过LSN可以记录每个页写入重做日志时的LSN的大小。前面说过重做日志记录的是对页的修改,所以在页的数据结构中也有FIL_PAGE_LSN来记录该页的LSN

55c58595622947b68e549a4f49ed1944.png

如果重做日志记录到LSN=3906时突然宕机了,并且事务提交了,这时候last checkpoint at=3696,log sequence number=3906,也就是右边的两个页没有实际应用到页里面(也就是事务的结果没最终落地),数据库恢复时,就会吧那两个页应用到对应页中。

Log Sequence number:表示当前的LSN

Log flushed up to:表示刷新到重做日志文件的LSN

Last checkpoint at:表示刷新到磁盘的LSN

数据库恢复时,只需要从Last checkpoint at的位置开始恢复就可以,也就是上面讲的例子 

redo.log的写入特点

从上面的图示中可以看出,redo.log是顺序写的,顺序写的好处就是每次写的时候会用做磁盘寻址,就相当大程度的提高写入效率。这一点很多中间件都会有使用到,比如RocketMQ,Kafka等数据的写入

总结一下

Mysql Innodb数据库引擎的在处理事务提交时是通过两段式提交来完成的。通过结合redo.log,bin.log来完成这个两段式提交的动作。但由于各自文件写入磁盘的时机不同,其在实际存储时的顺序也可能不一样。InnoDB通过三个LSN记录数据库恢复时应该从哪个位置开始,并且恢复时先遍历redo.log,只要是commit状态的直接提交,如果是prepare状态的会检查是否提交bin.log,如果有则提交,如果没有,则不提交

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

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

相关文章

Flink处理函数(2)—— 按键分区处理函数

按键分区处理函数(KeyedProcessFunction):先进行分区,然后定义处理操作 1.定时器(Timer)和定时服务(TimerService) 定时器(timers)是处理函数中进行时间相关…

LeetCode_11_中等_盛最多水的容器

文章目录 1. 题目2. 思路及代码实现(Python)2.1 双指针 1. 题目 给定一个长度为 n n n 的整数数组 h e i g h t height height 。有 n n n 条垂线,第 i i i 条线的两个端点是 ( i , 0 ) (i, 0) (i,0) 和 ( i , h e i g h t [ i ] ) (i…

联想M7268、7208打印机加粉清零方法

联想小新M7268激光一体机基本参数 产品类型 黑白激光多功能商用一体机 涵盖功能 打印/复印/扫描 最大处理幅面 A4 耗材类型 鼓粉分离 耗材容量 硒鼓LD2268:10000页,墨粉LT2268:1000页 双面功能 手…

Linux常用的管线命令(pipe)

只介绍命令和对应的功能,详细用法可针对性的自行搜索 管线命令基本上都是对文本进行截取的功能,据我观察,他们基本上会以行为单位。 以下命令都可以用在管道上,但是有些也可以单独使用。 以下演示的文件是用last | head -n 12 >…

你知道Mysql的架构吗?

msyql分为server曾和存储引擎层 server层包括了连接器(管理连接,权限验证)、查询缓存(命中直接返回结果)、分析器(词法分析,语法分析)、优化器(执行计划生成,索引选择)、…

java.lang.IllegalArgumentException: When allowCredentials is true

1.遇到的错误 java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a…

vue echarts地图

下载地图文件: DataV.GeoAtlas地理小工具系列 范围选择器右侧行政区划范围中输入需要选择的省份或地市,选择自己想要的数据格式,这里选择了geojson格式,点右侧的蓝色按钮复制到浏览器地址栏中,打开的geojson文件内容…

gRPC-gateway使用介绍

gRPC-gateway 参考资料:gRPC-Gateway使用指南 服务中,使用了gRPC gateway(代理)来将外部的http请求映射为内部rpc调用。 proto文件示例: // 导入google/api/annotations.proto import "google/api/annotations…

Oracle 19c rac集群管理 -------- 集群启停操作过程

Oracle rac集群启停操作过程 首先查看数据库的集群的db_unique_name SQL> show parameter nameNAME TYPE VALUE ------------------------------------ ----------- --------------------------- cdb_cluster_name …

Android Dialog 显示不全的问题

前言:开发的时候发现一些运行到手机里的dialog显示不全,只显示一半左右 问了下chatgpt发现没有任何头绪,于是开始自己慢慢分析 显示去掉了原有的dialog的style发现问题解决了,但在原有基础上如何解决呢? 先看看xml&a…

MYSQL之索引语法与使用

索引分类 分类 含义 特点 关键字 主键索引 针对表中主键创建的索引 默认自动创建,只能有一个 PRIMARY 唯一索引 …

【UE】在控件蓝图中通过时间轴控制材质参数变化

效果 步骤 1. 新建一个控件蓝图和一个材质 2. 打开材质,设置材质域为用户界面,混合模式设置为“半透明” 在材质图表中添加两个参数来控制材质的颜色和不透明度 3. 对材质创建材质实例 4. 打开控件蓝图,在画布面板中添加一个图像控件 将刚…

DC-8靶机做题记录

靶机下载地址: 链接:https://pan.baidu.com/s/1jPMYoyFZXqr7sVMElHqGcw?pwdypq9 提取码:ypq9 参考: 【DC系列靶机DC8通关讲解】 https://www.bilibili.com/video/BV1R84y1H7rk/?share_sourcecopy_web&vd_source12088c392…

指针数组与数组指针

数组指针与指针数组 动态数组 扩容:空间不够,重新申请2倍大小的连续空间,拷贝元素后,释放旧空间 动态数组区别于静态数组,其不具备begin(),end()操作 //动态一维数组int n 10;int *a new int[n];//可以输入n值&…

(完整代码)R语言中利用SVM-RFE机器学习算法筛选关键因子

前言 自用生信代码, 花费一个多月写下来的。自学R以来第一次写600多行的代码。我的文章已经发表,如对您的研究有帮助希望可以引用一下。文章点我 SVM-RFE 主要是借助e1071包, 实现mSVM-REF识别并筛选关键基因,没有安装的小伙伴…

SpringBoot3(一)动力节点总结

目录 0、有用的新特性 一、Record 1.1、Record的介绍 1.2、Record的声明 1.3、Record的创建 0、有用的新特性 JDK8-19 新增了不少新特性,这里我们把实际常用的新特性,给大家介绍一下,包括以下几个方面: Java RecordSwich 开…

Gold-YOLO(NeurIPS 2023)论文与代码解析

paper:Gold-YOLO: Efficient Object Detector via Gather-and-Distribute Mechanism official implementation:https://github.com/huawei-noah/Efficient-Computing/tree/master/Detection/Gold-YOLO 存在的问题 在过去几年里,YOLO系列已经…

东南大学博士,华为上班5年,月薪达到4万4000,年终奖近10万

东南大学博士,华为上班5年,月薪达到4万4000,年终奖近10万 近日有华为员工爆料真实薪资,该网友是东南大学2018级博士,华为工作近5年,薪资达到4万4000,年终奖近10W。 该网友华为职场履历如下&am…

Qt6入门教程 10:菜单栏、工具栏和状态栏

目录 一.菜单栏 1.Qt Designer 1.1添加菜单和菜单项 1.2添加二级菜单 1.3给菜单和菜单项添加图标 1.4给菜单项添加功能 2.纯手写 二.工具栏 1.Qt Designer 1.1添加工具栏按钮 1.2工具栏的几个重要属性 2.纯手写 三.状态栏 1.Qt Designer 2.纯手写 用Qt Creator新…

iptables命令详解

简介 iptables 是 Linux 系统中用于配置 IPv4 数据包过滤规则的工具。它是 Linux 内核中 Netfilter 框架的一部分,通过设置规则,可以实现网络包的过滤、NAT 转发、端口映射等功能。 基本概念 表(Tables): filter 表…