数据库的事务的并发问题和四种隔离级别

1. 数据并发问题

MySQL是一个客户端/服务器架构的软件,可以有若干个客户端与之连接,连接上之后,就可以称之为一个会话(Session),对于服务器来说可能同时处理多个Session,也就是对服务器来说可能同时处理多个事务。但是由于事务的隔离性,理论上如果多个事务有对同一个表中的数据进行的操作,他们的执行顺序应该按照事务到达的顺序进行排队(也叫序列化),但是这样对性能影响太大,比如SessionA,SessionB,SessionC都提交了一个事务,事务到达的顺序为A -> C -> B

Untitled Diagram.drawio-4.png

对比上面的图片我们发现虽然序列化可以满足事务的隔离性问题,但是对性能影响太大,难道就没有什么两全其美的方法吗?在解决问题之前,我们得先明白同时处理多个Session时可能会出现一系列并发问题,具体总结为以下几种:

  • 脏写
  • 脏读
  • 不可重复读
  • 幻读

创建一个表tb_student,数据如下:
image.png

下面我将根据该表数据进行通过举例+说明的方式进行解释。

1.1 脏写(Dirty Write)

脏写示意图:

执行次序Session ASession B
1事务开始
2事务开始
3UPDATE tb_student SET name = ‘lisi’ WHERE stu_id = 1
4UPDATE tb_student SET name = ‘wangwu’ WHERE stu_id = 1
5事务提交
6事务回滚
  • 前提事件: Session A和Session B各自开启了一个事务,并且他们都修改了同一个表的同一个字段

  • 附加事件: Session A在将"zhangsan"修改为"wangwu"后并提交事务,Session B却回滚了事务

  • 导致结果: 本该成功修改的"wangwu"又变回了"zhangsan",由于SessionA修改了一个未提交的数据,导致SessionA修改数据失败,这就是脏写问题。

1.2 脏读(Dirty Read)

脏读示意图:

执行次序Session ASession B
1事务开始
2事务开始
3UPDATE tb_student SET name = ‘lisi’ WHERE stu_id = 1
4SELECT * FROM tb_student WHERE stu_id = 1;(此时name=“lisi”)
5事务提交
6事务回滚
  • 前提事件: Session A和Session B各自开启了一个事务,Session A查询数据,Session B更改数据,它们的操作都是针对同一个表的。

  • 附加事件: 并且Session A在查询数据之前,Session B对数据进行了修改。此时Session A 读到的数据name值为"lisi",但是由于Session B 回滚事务。

  • 导致结果: name的实际值变又回了"zhangsan",此时Session A读到了一个未提交"脏数据",这就是脏读。

1.3 不可重复读(NON-REPEATED READ)

不可重复读示意图:

执行次序Session ASession B
1事务开始
2事务开始
3SELECT * FROM tb_student WHERE stu_id = 1;(此时name=“zhangsan”)
4UPDATE tb_student SET name = ‘lisi’ WHERE stu_id = 1
5事务提交
6SELECT * FROM tb_student WHERE stu_id = 1;(此时name=“lisi”)
7事务提交

前提事件: Session A和Session B各自开启了一个事务,Session A查询数据, Session B更改数据,它们的操作都是针对同一个表

附加事件: Session A的事务中进行了两次(或多次)查询,在两次查询之间,Session B中的事务对表中的数据进行了修改

导致结果: 两次(或多次)查询的结果不一样,这就是不可重复读问题

1.4 幻读(Phantom)

幻读示意图:

执行次序Session ASession B
1事务开始
2事务开始
3SELECT * FROM tb_student(此时只读到一条数据)
4INSERT INTO tb_student VALUES(2,‘lisi’,‘男’,19)
5事务提交
6SELECT * FROM tb_student;(此时读到了两条数据)
7事务提交

前提条件: Session A和Session B各自开启了一个事务,Session A查询多条数据, Session B插入新数据,它们的操作都是针对同一个表的

附加条件: Session A的事务中进行了两次(或多次)查询,在两次查询之间,Session B中的事务在表中新增数据

导致结果: SessionA再次读取同一个表,读到了先前没读到的记录,就像产生了幻觉,这就是幻读问题

2. 四种隔离级别

前面所提到的并发问题亦有轻重之分:脏写 > 脏读 > 不可重复读 > 幻读

我们可以为了提高性能,根据业务的需要进行一定的取舍,这时就需要通过设置隔离级别来实现了,接下来我来为大家介绍一下SQL中的四种隔离级别,以及分别解决了前面提到的哪些并发问题。

注意:由于脏写问题太过恶劣,数据库不允许这种行为,因此所有的隔离级别都是在解决脏写问题的前提下谈的

SQL标准中设立了下面4种隔离级别(级别从低到高):

  • READ UNCOMMITTED:读未提交,在该隔离级别,所有事务都可以看到其他未提交事务的执行结果。不能避免脏读、不可重复读、幻读。

  • READ COMMITED:读已提交:它满足了隔离的简单定义:一个事务只能看见已提交事务所做的改变。这是绝大多数数据库系统的隔离级别(MySQL不是)。可以避免脏读

  • REPEATABLE READ:可重复读,如果事务B对表中的数据进行了修改并提交,那么事务A多次读到的数据内容都相同。可以避免脏读、不可重复读,这也是MySQL中的默认隔离级别。

    image.png

  • SERIALIZABLE:可序列化,确保事务可以从一个表中读取相同的行。在这个事务持续期间,禁止其他事务对该表进行任何操作。解决了所有并发问题,但是性能十分低下。
    可总结为下面的表格:

隔离级别解决脏读解决不可重复读解决幻读
READ UNCOMMITTEDNONONO
READ COMMITEDYESNONO
REPEATABLE READYESYESNO
SERIALIZABLEYESYESYES

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

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

相关文章

element-ui中el-radio-group组件绑定点击事件触发多次的解决办法

1、需求 电商首页需求,需要做个单选框,然后点击选中切换图标方向及更换价格升倒序,如下图: 从官网文档看,单选框支持change event,使用click加载按钮处不会触发选中 但是使用 click.native 事件不做处理…

LeetCode 2924.找到冠军 II:脑筋急转弯——只关心入度

【LetMeFly】2924.找到冠军 II:脑筋急转弯——只关心入度 力扣题目链接:https://leetcode.cn/problems/find-champion-ii/ 一场比赛中共有 n 支队伍,按从 0 到 n - 1 编号。每支队伍也是 有向无环图(DAG) 上的一个节…

The C programming language (second edition,KR) exercise(CHAPTER 2)

E x c e r c i s e 2 − 1 Excercise\quad 2-1 Excercise2−1&#xff1a;输出结果如图1和图2所示&#xff0c;这道练习题需要文章1和文章2的知识。 #include <stdio.h> #include <limits.h>float getFloat(char sign, unsigned char exp, unsigned mantissa); do…

【Django开发】0到1美多商城项目md教程第7篇:登录,1. 互联开发者申请步骤【附代码文档】

美多商城完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;欢迎来到美多商城&#xff01;&#xff0c;项目准备。展示用户注册页面&#xff0c;创建用户模块子应用。用户注册业务实现&#xff0c;用户注册前端逻辑。图形验证码&#xff0c;图形验证码接口设…

代码随想录算法训练营第二十五天|216.组合总和III、17.电话号码的字母组合

216. 组合总和 III 思路&#xff1a; 本题就是在[1,2,3,4,5,6,7,8,9]这个集合中找到和为n的k个数的组合。 相对于 77. 组合&#xff0c;无非就是多了一个限制&#xff0c;本题是要找到和为n的k个数的组合&#xff0c;而整个集合已经是固定的了[1,...,9]。 本题k相当于树的深…

vue列表列表过滤

对已知的列表进行数据过滤(根据输入框里面的内容进行数据过滤) 编写案例 通过案例来演示说明 效果就是这样的 输入框是模糊查询 想要实现功能&#xff0c;其实就两大步&#xff0c;1获取输入框内容 2根据输入内容进行数据过滤 绑定收集数据 我们可以使用v-model去双向绑定 …

Java 使用 ant.jar 执行 SQL 脚本文件

Java 使用 ant.jar 执行 SQL 脚本文件&#xff0c;很简单。 在 pom.xml 中导入 ant 依赖 <dependency><groupId>org.apache.ant</groupId><artifactId>ant</artifactId><version>1.10.11</version> </dependency>sql 脚本文件…

【2024】使用Rancher管理k8s集群和创建k8s集群

Rancher管理k8s集群及创建k8s集群。 Rancher版本为:2.8.2目录 rancher管理k8s集群rancher创建k8s集群rancher管理k8s集群 使用rancher管理已经存在的k8s集群。 本部分内容需要自行准备好k8s集群及rancher平台,部署请看本人其他文章 。 登录到rancher平台后,点击集群管理,…

c++修炼之路之vector模拟实现

目录 前言&#xff1a; 一&#xff1a;在STL的开源代码中的vector的实现 二&#xff1a;模拟实现 1.数据成员size()capacity() 2.resizereserve 3.构造函数析构函数赋值重载 4.迭代器[] 5.push_backinserterase迭代器失效问题 三&#xff1a;测试用例和全部代码 接下…

【LAMMPS学习】八、基础知识(1.8)键的断裂

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

【C++庖丁解牛】哈希表/散列表的设计原理 | 哈希函数

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 前言1.哈希概念2.哈希冲突…

推荐七个Python效率工具!

为了提高效率&#xff0c;我们在平时工作中常会用到一些Python的效率工具&#xff0c;Python作为比较老的编程语言&#xff0c;它可以实现日常工作的各种自动化。为了更便利的开发项目&#xff0c;这里给大家推荐几个Python的效率工具。 1、Pandas-用于数据分析 Pandas是一个强…

复杂DP算法(动态规划)

复杂DP算法 一、线性DP例题1、鸣人的影分身题目信息思路题解 2、糖果题目信息思路题解 二、区间DP例题密码脱落题目信息思路题解 三、树状DP例题生命之树题目信息思路题解 一、线性DP 例题 1、鸣人的影分身 题目信息 思路 题解 #include <bits/stdc.h> #define endl …

ZISUOJ 数据结构-线性表

题目列表&#xff1a; 问题 A: 逆序链表建立 思路&#xff1a; 可以使用头插法插入所有元素后正序遍历输出或者使用尾插法逆序遍历&#xff0c;推荐使用双链表。这是链表系列的第一个题&#xff0c;那这个题下面的参考题解的各种解法我会尽可能写全一些。 参考题解1&#xff0…

【OTA】STM32-OTA升级——持续更新

【OTA】STM32-OTA升级——持续更新 文章目录 前言一、ymodem串口协议1、Ymodem 协议2、PC3、蓝牙4、WIFI云平台 二、UDS车载协议1.UDS协议 总结 前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、ymodem串口协议 1、Ymodem 协议 STM32 Ymodem …

【I/O】基于事件驱动的 I/O 模型---Reactor

Reactor 模型 BIO 到 I/O 多路复用 为每个连接都创建一个线程 假设我们现在有一个服务器&#xff0c;想要对接多个客户端&#xff0c;那么最简单的方法就是服务端为每个连接都创建一个线程&#xff0c;处理完业务逻辑后&#xff0c;随着连接关闭线程也要销毁&#xff0c;但是…

每日一题(leetcode238):除自身以外数组的乘积--前缀和

不进阶是创建两个数组&#xff1a; class Solution { public:vector<int> productExceptSelf(vector<int>& nums) {int nnums.size();vector<int> left(n);vector<int> right(n);int mul1;for(int i0;i<n;i){mul*nums[i];left[i]mul;}mul1;for…

前端开发攻略---根据音频节奏实时绘制不断变化的波形图。深入剖析如何通过代码实现音频数据的可视化。

1、演示 2、代码分析 逐行解析 JavaScript 代码块&#xff1a; const audioEle document.querySelector(audio) const cvs document.querySelector(canvas) const ctx cvs.getContext(2d)这几行代码首先获取了 <audio> 和 <canvas> 元素的引用&#xff0c;并使用…

Java编程练习之抽象类与抽象方法

使用抽象类和抽象方法时&#xff0c;需要遵循以下原则&#xff1a; 1&#xff09;在抽象类中&#xff0c;可以包含抽象方法&#xff0c;也可以不包含抽象方法&#xff0c;但是包含了抽象方法的类必须被定义为抽象类&#xff1b; 2&#xff09;抽象类不能直接被实例化&#xf…

BugKu:Flask_FileUpload

Flask_FileUpload 解题思路 查看源码&#xff1a; 编写上传的文件 获得结果 小结 文件上传漏洞&#xff1a; 文件上传漏洞是指用户上传了一个可执行的脚本文件&#xff0c;并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直接和有效的&#xff0c;“文件上…