探讨MySQL事务特性和实现原理

news2024/11/28 13:53:58

一、概念

事务 一般指的是逻辑上的一组操作,或者作为单个逻辑单元执行的一系列操作,一个事务中的所有操作会被封装成一个不可分割的执行单元,这个单元的所有操作要么全部执行成功,要么全部执行失败,只要其中任意一个操作执行失败,整个事务就会执行回滚操作。

二、事务的特性以及类型介绍

2.1 事务特性

原子性(atomicity)

事务的原子性指的是构成事务的所有操作要么全部执行成功,要么全部执行是失败。

一致性(consistency)

事务的一致性指的是事务执行之前和执行之后,数据始终处于一致的状态。

隔离性(isolation)

事务的隔离性指的是并发执行的两个事务之间互不干扰,也就是说,一个事务执行的过程中是无法看到其他事务运行过程的中间状态的。

👨‍注意:MySQL是通过锁个MVCC机制来保证事务的隔离性。

持久性(duration)

事务的持久性指的是一旦事务被提交后,此事务对数据的更改操作会被持久化到数据库中,并且不会被回滚。

2.2 两种事务类型介绍

  • 本地事务
  • 分布式事务

本地事务

通常基于关系型数据库控制的事务可以称作为传统事务或者本地事务。

本地事务的执行流程

  1. 客户端开始事务操作之前,需要开启一个连接回话;
  2. 开始回话之后,客户端发起开启事务的指令;
  3. 事务开始后,客户端发送各种SQL语句处理数据;
  4. 正常情况下,客户端会发起提交事务的指令,如果发生异常情况,客户端会发起回滚事务命令;
  5. 上述流程完成后,关闭会话。

✔本地事务是有资源管理器在本地进行管理的。

本地事务的缺点在于:

  • 不具备分布式事务的处理能力
  • 一次事务过程只能连接一个支持事务的数据库,既不能用于多个事务性数据库。

三、并发事务会带来的哪些问题?

更新丢失(脏写)

当两个会在两个以上的事务同时操作同一行数据,并给予最初选定的值更新该行数据时,视为事务之间是无法感知彼此的存在的,所以会出现最后的更新操作会覆盖之前其他事务完成的更新操作。

举个例子:

张三的账户为100元,当前有两个事务:事务1和事务2,事务1是将张三账户余额增加100元,事务2是将张三余额增加200,起初事务1和事务2同时读到张三的账户余额都是100元,然后事务1和事务2分别更新张三月,假设事务1先于事务2提交,但是最近两个事务都提交后张三的余额为300元(正常情况应该是400元),也就是说:后提交的事务2覆盖了事务1的更新操作,这就是所谓的更新丢失,更新丢失(脏写)本质上是写操作的冲突,然而解决脏写的方式是让每个事务串行方式执行,保证事务按照一定的顺序执行写操作。

脏读

一个事务读取到另一个事务未提交的数据。比如:事务1正在对张三的余额增加100元,在这个事务没提交之前,另一个事务2读取了正在修改的这条数据,如果没有事务的控制下,第二条事务就会读取到没有被提交的脏数据,并且对脏数据丛下一步的处理,此时就会产生未提交数据的依赖关系,通常这种现象被称为 脏读,也就是说:脏读是一个事务读取了另一个事务没提交的数据。

🤔脏读本质上是读写操作的冲突,解决方法是先写后读,也就是写完之后再读。

不可重复读

一个事务读取了某些数据,在一段时间后,这个事务再次读取之前读过的数据,此时发现读取的数据发生了变化,或者其中某些数据记录已经被删除,这种现象被称为:不可重复读,即同一个事务,使用同样的查询语句,在不同时刻读取到的结果不一致。

不可重复读的本质上也是读写操作冲突,解决方法是先读后写,也就是读完之后再写。

幻读

一个事务按照相同的查询条件重新读取之前读过的数据,此时发现其他事务插入了满足当前查询条件的新数据,数据结果集变多,这种现象称为幻读,即一个事务两次读取一个范围的数据记录,两次读到的结果不同。

幻读的本质上也是读写操作冲突,解决方法是先读后写,也就是读完之后再写。

那到这里,很多小伙伴就有疑问,同样本质都是读写操作冲突,解决方法是先读后写,不可重复读和幻读到底有何区别?,我下面见简单解释一下:

1️⃣ 不可重复读的重点在于更新和删除操作,而幻读的重点在于插入操作。
2️⃣ MySQL使用锁机制实现事务的隔离级别时,在可重复读隔离级别中,SQL语句第一个读取到数据后,会将相应的数据加锁,使得其他事务无法修改和删除这些数据,通过锁的方式实现可重复读。但是这种方法无法对新数据的插入加锁,如果事务1读取了数据,或者修改和删除了数据,事务2还可以进行插入操作,导致事务1莫名其妙地多了一条之前没有的数据,这就是幻读。
3️⃣ 所以,幻读是无法通过锁机制来避免,需要使用串行化的事务隔离级别,但是这种事务隔离级别会大大降低数据库的并发能力。

✔MySQL是通过MVCC(多版本并发控制)机制来避免不可重复读和幻读的。

四、MySQL事务的隔离级别

使用下面的命令可以查询全局级别和会话级别的事务隔离级别:

# 默认数据库的事务隔离级别为:可重复读(REPEATABLE-READ)
SELECT @@global.tx_isolation;
SELECT @@session.tx_isolation;
SELECT @@tx_isolation;

五、多版本并发控制MVCC

Multi-Version Concurrency Control多版本并发控制,MVCC是一种并发控制的方法,一般在数据库管理系统中,实现对数据库的并发访问。

MVCC比锁的优势

可以将MVCC看成行级别锁的一种妥协,它在许多情况下避免了使用锁,同时可以提供更小的开销。根据实现的不同,它可以允许非阻塞式读,在写操作进行时只锁定必要的记录。

MVCC的实现原理

MVCC的是通过保存数据澡某个时间点的快照来实现的,也就是说,不管事务执行多长的时间,每个事务看到的数据都是一致的。根据事务的开始时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。InnonDB主要通过为每一行记录添加两个额外的隐藏的值来实现MVCC,这两个值一个记录这行数据何时被创建,另外一个记录这行数据何时过期(或者被删除)。但是InnoDB并不存储这些事件发生时的 实际时间 ,相反它只存储这些事件发生时的系统 版本号(version) 。这是一个随着事务的创建而不断增长的数字。每个事务在事务开始时会记录它自己的系统版本号。每个查询必须去检查每行数据的版本号与事务的版本号是否相同。

《高性能MySQL》书籍中介绍到:

MVCC只在REPEATABLE READREAD COMMITTIED两个隔离级别下工作,其他两个隔离级别都和MVCC不兼容,因为READ UNCOMMITTED总是读取最新的数据行,而不符合当前事务版本数据行,而SERIALIZABLE串行化隔离级别则会对所有读取的行都加锁。

接下来举个例子说明在可重复读事务隔离级别下,MVCC机制是如何完成增删改查操作的。

  • 查询操作(SELECT)

在查询操作中,InnoDB存储引擎跟根据以下两个条件查询对应的行记录,只有满足对应条件才会被返回:

1️⃣ 只查找不晚于当前事务版本的数据行,也就是说,InnoDB存储引擎只会查找版本号小于或者等于当前事务版本的数据行,这些数据行要么在该事务开始前就存在,要么就是事务本身插入或者更新的行。
2️⃣ 对于数据删除,数据行删除的版本要么还没有被定义,要么大于当前事务的版本号,只有这样才能确保事务读到的行,在事务开始前并没有被删除。

举个例子,存在 事务A事务B 两个事务,事务A中存在两套相同的SELECT语句,事务B存在一条UPDATE语句,事务A 的第一条查询语句在事务B提交之前执行,第二条查询语句在 事务B 提交之后执行,事务A 如下所示:

-- 事务A操作
START TRANSACTION;
SELECT * FROM account WHERE id = 1;     //在事务B提交之前执行
SELECT * FROM account WHERE id = 1;     //在事务B提交之后执行
COMMIT;

事务B:

-- 事务B操作
START TRANSACTION;
UPDATE account SET balance = balance+100 WHERE id = 1;
COMMIT;

✔结论:如果没有使用MVCC机制,则事务A中的第一条SELECT语句读取的数据是修改前的数据,而第二条SELECT语句读取的是修改后的数据,两次读取的数据不一致,想想,那不就乱了吗😨? 如果使用了MVCC机制,无论事务B如何修改数据,事务A的两条查询语句的到的结果始终是一致的。

  • 插入操作(SELECT)

在插入操作中,InnoDB会将新插入的每一条行记录的当前系统版本包保存为行版本号。

比如:向account表插入一条数据,同时MVCC的两个版本号分别为create_versiondelete_versioncreate_version代表创建行的版本号,delete_version代表删除行的版本号,另外还有一个事务ID字段,如下面所示:

INSERT INTO account(id, name, balance) values(1001, 'austin', 100);
复制代码

对应的版本号信息如下表:

idnamebalancetransaction_idcreate_versiondelete_version
1001austin10011未定义

可以看出,当向数据表新增记录时,需要设置保存行的版本号,而删除行的版本号未定义。

  • 更新操作(SELECT)

在更新操作中,InnoDB存储引擎会插入一行新记录,并保存当前系统的版本号为新记录行的版本号,同时保存当前系统的版本号到原来数据行作为删除标识。比如:将account数据表中id为1001的用户账户月增加100元,对应SQL如下:

UPDATE account SET balance = balance+100 WHERE id = 1001;
复制代码

执行SQL, 在MVCC机制下的更新操作如下表所示:

idnamebalancetransaction_idcreate_versiondelete_version
1001austin100112
1001austin20022未定义

可以明显看出,执行更新操作时,MVCC机制是先将原来的数据复制一份,将balance字段增加100后,再讲create_version字段的值设置为当前系统的版本号,而delete_version字段的值未定义。

注意的是:原来的行会被复制到Undo Log中。

  • 删除操作(SELECT)

在删除操作中,InnoDB存储引擎会保存删除的每一个行记录当前的系统版本号,作为删除标识。比如:删除account数据表中id为1001的数据,SQL如下所示:

DELETE FROM account WHERE id = 1001;
复制代码

对应MVCC机制下的删除操作如下表所示:

idnamebalancetransaction_idcreate_versiondelete_version
1001austin200323

可以看出,当删除数据表数据行时,MVCC机制会将当前系统的版本号写入删除数据行版本字段delete_version中,以此来表示当前数据行已经被删除。

六、总结

本文主要讲述了事务的特性、类型和本地事务和分布式事务的区别,通过不同的示例解释并发事务带来的更新丢失、脏读、不可重复读、幻读的问题,同时介绍了多版本并发控制MVCC的实现原理。

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

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

相关文章

《Terraform 101 从入门到实践》 第四章 States状态管理

《Terraform 101 从入门到实践》这本小册在南瓜慢说官方网站和GitHub两个地方同步更新,书中的示例代码也是放在GitHub上,方便大家参考查看。 军书十二卷,卷卷有爷名。 为什么需要状态管理 Terraform的主要作用是管理云平台上的资源&#xff…

个人学习系列 - 解决拦截器操作请求参数后台无法获取

由于项目需要使用拦截器对请求参数进行操作,可是请求流只能操作一次,导致后面方法不能再获取流了。 新建SpringBoot项目 1. 新建拦截器WebConfig.java /*** date: 2023/2/6 11:21* author: zhouzhaodong* description:*/ Configuration public class W…

Docker-consul的容器服务更新与发现

一.Consul概述1.1 什么是服务注册与发现服务注册与发现是微服务架构中不可或缺的重要组件。起初服务都是单节点的,不保障高可用性,也不考虑服务的压力承载,服务之间调用单纯的通过接口访问。直到后来出现了多个节点的分布式架构,起…

Threejs中的Shadow Mapping(阴影贴图)

简而言之,步骤如下: 1.从灯光位置视点(阴影相机)创建深度图。 2.从相机的位置角度进行屏幕渲染,在每个像素点,比较由阴影相机的MVP矩阵计算的深度值和深度图的值的大小,如果深度图值小的话&…

Office Server Document Converter Lib SDK Crack

关于 Office Server 文档转换器 (OSDC) 无需 Microsoft Office 或 Adob​​e 软件即可快速准确地转换文档。antennahouse.com Office Server 文档转换器 (OSDC) 会将您在 Microsoft Office(Word、Excel、PowerPoint)中创建的重要文档转换为高质量的 PDF …

【编程基础之Python】2、安装Python环境

【编程基础之Python】2、安装Python环境安装Python环境在Windows上安装Python验证Python运行环境在Linux上安装Python验证Python运行环境总结安装Python环境 所谓“工欲善其事,必先利其器”。在学习Python之前需要先搭建Python的运行环境。由于Python是跨平台的&am…

机器学习之K-means原理详解、公式推导、简单实例(python实现,sklearn调包)

目录1. 聚类原理1.1. 无监督与聚类1.2. K均值算法2. 公式推导2.1. 距离2.2. 最小平方误差3. 实例3.1. python实现3.2. sklearn实现4. 运行(可直接食用)1. 聚类原理 1.1. 无监督与聚类 在这部分我今天主要介绍K均值聚类算法,在这之前我想提一…

01-幂等性解释,问题及常用解决方案

目录 1. 幂等性简介 2. 后端如何解决幂等性问题 2.1 数据库层面 -> 2.1.1 防重表 -> 2.1.2 数据库悲观锁(不建议,容易出现死锁情况) -> 2.1.3 数据库乐观锁 -> 2.1.4 乐观锁CAS算法原理 2.2 锁层面 2.3 幂等性token层面 -> 2.3.1 简介文字描述: …

Java开发 - 问君能有几多愁,Spring Boot瞅一瞅。

前言 首先在这里恭祝大家新年快乐,兔年大吉。本来是想在年前发布这篇博文的,奈何过年期间走街串巷,实在无心学术,所以不得不放在近日写下这篇Spring Boot的博文。在还没开始写之前,我已经预见到,这恐怕将是…

中国社科院与美国杜兰大学金融管理硕士,让我们相遇在春暖花开时

在芸芸众生中,能拥有志同道合的朋友是一件多么幸运的事。人们常说:你是谁,就会遇见谁。走过半生才知道,看似命中注定的遇见谁、发生的事,其实都取决于自己。只有自己足够优秀,才能遇到更优秀的别人。在这个…

IT人的晋升之路——关于人际交往能力的培养

对于咱们的程序员来说,工作往往不是最难的,更难的是人际交往和关系的维护处理。很多时候我们都宁愿加班,也不愿意是社交,认识新的朋友,拓展自己的圈子。对外的感觉就好像我们丧失了人际交往能力,是个呆子&a…

【chatGPT】持续火热一路狂飙,简单了解下TA的功能和示例代码吧

🎉🎉 最近chatGPT持续火爆,一路狂飙,对应如何注册和使用的优质文章非常多。 所以,此篇文章除了整理chatGPT文章外,主要是讲解如何获取API Key进行接口的调用🎉🎉 目录1、chatGPT解读…

蓝牙单点技术实现路径介绍

本文主要介绍蓝牙设备与手机一对一相连的 蓝牙单点 技术。 准备工作 系统要求&#xff1a;蓝牙使用需要安卓 4.3 以及以上版本&#xff0c;智能生活 App SDK 从安卓 4.4 开始支持。Manifest 权限&#xff1a; <uses-permission android:name"android.permission.ACCE…

Fluent Python 笔记 第 3 章 字典和集合

3.1 泛映射类型 只有可散列 的数据类型才能用作这些映射里的键 字典构造方法&#xff1a; >>> a dict(one1, two2, three3) >>> b {one: 1, two: 2, three: 3} >>> c dict(zip([one, two, three], [1, 2, 3])) >>> d dict([(two, 2…

5. Spring 事务

文章目录1. Spring 事务简介2. Spring 事务角色3. Spring 事务属性3.1 事务配置3.2 案例&#xff1a;转账业务追加日志3.3 事务传播行为1. Spring 事务简介 Spring 事务作用&#xff1a;在数据层或业务层保障一系列的数据库操作同成功、同失败。 数据层有事务我们可以理解&am…

多传感器融合定位十三-基于图优化的建图方法其二

多传感器融合定位十二-基于图优化的建图方法其二3.4 预积分方差计算3.4.1 核心思路3.4.2 连续时间下的微分方程3.4.3 离散时间下的传递方程3.5 预积分更新4. 典型方案介绍4.1 LIO-SAM介绍5. 融合编码器的优化方案5.1 整体思路介绍5.2 预积分模型设计Reference: 深蓝学院-多传感…

Vue3 - 自定义指令封装

Vue3 - 自定义指令封装一. 自定义指令封装1.1 全局/局部注册自定义聚焦指令1.2 自定义指令相关参数1.3 自定义指令参数传递二. 总结一. 自定义指令封装 vue中有很多内置的指令&#xff0c;我们一般在开发中也经常用到&#xff0c;比如v-if&#xff0c;v-for等等。那么本篇文章…

Vue极简使用

Vue安装Vue模板语法安装Vue 安装nodejs 这里我安装的是14.5.4版本 https://nodejs.org/download/release/v14.15.4/解压后配置一下环境变量就行 安装cnpm镜像 (这个安装的版本可能过高&#xff0c;后面安装Vue可能出问题) npm install -g cnpm --registryhttps://registry…

二十二、Gtk4-ListView

GTK 4添加了新的列表对象GtkListView、GtkGridView和GtkColumnView。这个新特性在Gtk API参考—列表小构件概述中有描述。 GTK 4还有其他实现列表的方法。它们是GtkListBox和GtkTreeView&#xff0c;它们是从GTK 3接管的。在Gtk开发博客中有一篇关于Matthias Clasen所写的列表…

vscode执行Python输出exited with code=9009 in 0.655 seconds

vscode执行Python输出exited with code9009 in 0.655 seconds 想用vscode写个脚本&#xff0c;用自己电脑配置了下vscode的python环境&#xff0c;结果点击右上角三角图标运行时却只会输出exited with code9009 in 0.655 seconds 这就不太理解了&#xff0c;我在公司时是能正…