AAA 数据库事务隔离级别及死锁

目录

一、事务的四大特性(ACID)

1. 原子性(atomicity):

2. 一致性(consistency):

3. 隔离性(isolation):

4. 持久性(durability):

二、死锁的产生及解决方法

三、事务的四种隔离级别

0 .封锁协议

1 读未提交(Read uncommitted):

2. 读已提交(Read committed):

3. 可重复读(Repeatable read)

4. 串行化(Serializable)

四、MVCC(Multi-Version Concurrency Control)

1 为什么会有MVCC

2 MVCC在哪个隔离级别下才生效

3 ReadView是什么

五、不同隔离级别演示

演示准备

读未提交----->脏读

读已提交----->不可重复读

可重复读----->幻读

串行化


一、事务的四大特性(ACID)

1. 原子性(atomicity):

事务是一个原子操作,要么全部执行成功,要么全部执行失败。 事务的原子性确保一组逻辑操作,要么全部完成,要么完全不起作用。

2. 一致性(consistency):

事务失败,当前事务都会回滚,事务成功,其他事务可见

3. 隔离性(isolation):

事务的隔离性是指在并发执行的多个事务中,每个事务相互独立,互不影响

事务隔离级别越高,数据冲突的可能性就越小,但并发性能也会受到一定的影响。

4. 持久性(durability):

一个事务被提交之后。它对数据库中数据的改变是持久的,即使数据库发生故障,应用重启,也不应该对其有任何影响。

二、死锁的产生及解决方法

产生死锁的四个必要条件

  1. 互斥条件‌:进程对所分配的资源进行排他性控制,即资源在一段时间内只能被一个进程使用。
  2. 请求保持条件‌:一个进程已经获得至少一个资源,但又请求新的资源,而该资源被其他进程占用,导致该进程阻塞,但已获得的资源保持不放。
  3. 不可剥夺条件‌:进程已获得的资源在未使用完之前,不能被其他进程强行夺走,只能由获得该资源的进程主动释放。
  4. 环路等待条件‌:存在一种循环等待资源的链,链中每个进程已获得的资源同时被链中下一个进程请求,形成循环等待。

数据库死锁产生的原因及解决方案

数据库死锁产生的原因有以下几点:

  1. 多个事务同时访问同一资源,每个事务都试图获取其他事务已经持有的锁,导致互相等待,从而产生死锁。12
  1. 事务在获取锁时的顺序不同,也可能导致死锁。例如,事务A获得了资源X的锁,并尝试获取资源Y的锁,而事务B获得了资源Y的锁,并尝试获取资源X的锁。这种情况下,两个事务都无法继续执行,形成了死锁。4

解决数据库死锁的方案有以下几种:

  1. 保持锁的顺序一致:在多个事务请求资源的情况下,保持锁的请求顺序一致,可以避免死锁的发生。

  2. 尽量缩短事务的持有时间:事务持有锁的时间过长会增加死锁的风险。因此,在处理事务时,应尽量缩短事务的持有时间,尽快释放锁。

  3. 使用超时机制:如果一个事务等待锁的时间过长,可以使用超时机制来终止该事务,从而避免死锁的发生。

  4. 检测并解决死锁:数据库管理系统通常提供死锁检测机制,一旦检测出死锁,可以中止其中一个事务,从而解除死锁。同时,也可以优化锁的使用和重构事务来降低死锁的发生率。如果死锁频繁发生,可能需要增加资源,如提升服务器的处理能力或增加数据库的缓存空间。

三、事务的四种隔离级别

隔离级别脏读不可重复读幻读
读未提交可能出现可能出现可能出现
读已提交不会出现可能出现可能出现
可重复读不会出现不会出现可能出现
串行化不会出现不会出现不会出现

数据库事务的隔离级别有4种,由低到高分别为Read uncommitted 、Read committed 、Repeatable read 、Serializable 。在事务的并发操作中可能会出现脏读,不可重复读,幻读。

0 .封锁协议

一级封锁协议(读未提交):写加写锁,读不加锁。事务T在修改数据R之前必须对其加X锁,直到事务结束才释放。以及封锁协议可以防止修改丢失,并保证事务T是可恢复的。在一级封锁协议中,如果仅仅是读数据不对其进行修改,是不需要加锁的,所以它不能保证可重复读和不读“脏”数据。

二级封锁协议是(读已提交):写加写锁,读加临时锁。一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,读完后即可释放S锁。二级封锁协议除防止丢失修改,还可进一步防止读“脏”数据。在二级封锁协议中,由于读完数据即可释放S锁,所以它不能保证可重复读。

三级封锁协议(可重复读):写加写锁,读加事务锁。一级封锁协议加上事务T在读取数据R之前必须先对其加S锁,直到事务结束才释放。三级封锁协议可以防止丢失修改,读“脏"数据和不可重复读。

1 读未提交(Read uncommitted):

1.1 简述

一个事务读到了另一个事务还没有提交的数据。

1.2 事例

父亲要给儿子转账。但是转账时父亲不小心按错了数字,按成10万/月,该钱已经打到儿子的账户,但是事务还没有提交,就在这时,儿子去查看自己的储蓄卡,发现转多了9万,以为凭空多了9万非常高兴。但是父亲及时发现了不对,马上回滚差点就提交了的事务,将数字改成1万再提交。

1.3 分析

实际父亲给儿子转的还是1万,但是儿子看到的是10万。儿子看到的是父亲还没提交事务时的数据。这就是脏读。

2. 读已提交(Read committed):

2.1 简述

一个事务要等另一个事务提交后才能读取数据。

2.2 事例

儿子拿着父亲的信用卡去消费(卡里目前有10),当他买单时(父亲事务开启),收费系统事先检测到他的卡里有10万,就在这个时候!!父亲要把钱全部转出充当家用,并提交。当收费系统准备扣款时,再检测卡里的金额,发现已经没钱了(第二次检测金额当然要等待父亲转出金额事务提交完)。儿子就会很郁闷,明明卡里是有钱的…

2.3 分析

这就是读已提交,若有事务对数据进行更新操作时,读操作事务要等待这个更新操作事务提交后才能读取数据,可以解决脏读问题。但在这个事例中,出现了一个事务范围内两次相同的查询却返回了不同数据,这就是不可重复读。

3. 可重复读(Repeatable read)

3.1 简述

同一事务下,事务在执行期间,多次读取同一数据时,能够保证读取到的数据是一致的。

3.2 事例

儿子拿着信用卡去享受生活(卡里只有10万),当他买单时(事务开启,不允许其他事务的UPDATE修改操作),收费系统事先检测到他的卡里有10万。这个时候父亲不能转出金额了。接下来收费系统就可以扣款了。

3.3 分析

可重复读解决了不可重复读的问题。说到这里,应该明白的一点就是,不可重复读对应的是修改,即UPDATE操作。但是可能还会有幻读问题。因为幻读问题对应的是插入INSERT操作,而不是UPDATE操作。

3.4 什么时候会出现幻读?

3.4.1 简述

一个事务读取到了另一个事务新增的数据

3.4.2 事例

儿子某一天去消费,花了8千元,然后他的父亲去查看他今天的消费记录(全表扫描,儿子事务开启),看到确实是花了8千元,就在这个时候,儿子花了1万买了一部电脑,即新增INSERT了一条消费记录,并提交。当父亲打印儿子的消费记录清单时(儿子事务提交),发现花了1.8万元,似乎出现了幻觉,这就是幻读。

3.4.3 那怎么解决幻读问题?

串行化

4. 串行化(Serializable)

它是最高的事务隔离级别,在该级别下,事务串行化顺序执行,可以避免脏读、不可重复读与幻读。但是这种事务隔离级别效率最低,比较耗费数据库性能,一般不推荐使用。

四、MVCC(Multi-Version Concurrency Control)

MVCC原理底层就是通过read view 以及undo log来实现

1 为什么会有MVCC

频繁加锁会导致数据库性能低下,引入了MVCC多版本控制来实现读写不阻塞,提高数据库性能,在多版本并发控制中,为了保证数据操作在多线程过程中,保证事务隔离的机制,降低锁竞争的压力,保证较高的并发量。在每开启一个事务时,会生成一个事务的版本号,被操作的数据会生成一条新的数据行(临时),但是在提交前对其他事务是不可见的,对于数据的更新(包括增删改)操作成功,会将这个版本号更新到数据的行中,事务提交成功,将新的版本号更新到此数据行中,这样保证了每个事务操作的数据,都是互不影响的,也不存在锁的问题。

MVCC机制的实现就是通过read-view机制与undo版本链比对机制,使得不同的事务会根据数据版本链对比规则读取同一条数据在版本链上的不同版本数据。

2 MVCC在哪个隔离级别下才生效

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

InnoDB行数据默认隐藏列

InnoDB在每行数据都增加三个隐藏字段:一个唯一行号,一个记录创建的版本号,一个记录回滚的版本号。

3 ReadView是什么

在我们平时执行一个事务的时候,就会生成一个ReadView,ReadView的组成结构大致如下:
9571c88a62d502cd231c77657a5efb09.png

read view 参数解释

1.creator_trx_id: 当前事务id

没什么可解释,就是当前事务ID

2.m_ids:所有活跃事务的事务id

当前所有未提交的事务id构成的集合

3.min_trx_id: m_ids里最小的事务id值

当前所有未提交的事务id构成的集合里的最小的哪个事务id

4.max_trx_id: 最大事务id

下一个即将创建的事务id

Read View快照的生成时机

repeatable read级别

语句级快照

read committed级别

事务级的快照

版本链比对规则

  1. 如果被访问版本的trx_id属性值与rv中的creator_trx_id值相同 可见
  2. 如果被访问版本的trx_id属性值小于rv中的min_trx_id值 可见
  3. 如果被访问版本的trx_id属性值大于或等于rv中的max_trx_id值 不可见
  4. 如果被访问版本的trx_id属性值在rv的min_trx_id和max_trx_id之间
    4.1 trx_id在m_ids中 不可见
    4.2 trx_id不在m_ids中 可见

MVCC比对练习题

06e827b30f67c4e591f2d198c14758e0.png

在同一个事务里,针对id=1的记录,当前事务ID分别为200,99,38,15,5的行记录能查询到么,是可见的么?

200不可见、99可见、38可见、15不可见、5可见

思考题:为啥要把最小的事务id值单独作为一个字段?

时间复杂度,难道要从所有未提交的集合中去找么,依次遍历

1.版本说明

这里是8.0.33

5c1623f09669cf9cd4a79c473fd5027d.png

2. 查询mysql全局事务隔离级别

2.1 查询命令

select @@global.transaction_isolation;

2.2 默认隔离级别如下

bdb1bf7452a38d22f91a30834735c084.png

3. 注意事项

低版本的查询语句是select @@global.tx_isolation;

五、不同隔离级别演示

演示准备

创建sql语句准备

CREATE TABLE user (
	--自增ID
    id INT NOT NULL AUTO_INCREMENT,
    --姓名
    name VARCHAR(50) NOT NULL,
    --年龄
    age INT NOT NULL,
    --主键
    PRIMARY KEY (id)
);

数据准备

--插入一条记录,id为1,name为'张三',age为20
INSERT INTO user(id, name, age) VALUES (1, '张三', 20);
-- 插入一条记录,id为2,name为'李四',age为30
INSERT INTO user(id, name, age) VALUES (2, '李四', 30);
-- 插入一条记录,id为3,name为'王五',age为25
INSERT INTO user(id, name, age) VALUES (3, '王五', 25);
-- 插入一条记录,id为4,name为'赵六',age为28
INSERT INTO user(id, name, age) VALUES (4, '赵六', 28);

读未提交----->脏读

设置当前会话隔离级别为读未提交

20111f34644f04881aba5eafc6df617a.png

SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;

1、a 事务(客户端1) 修改 、未提交

76c6d2204f2c81302161453ebc2748ac.png

2、b事务(客户端2) 读该数据

f8c53d19c3b32a9c0209607a53f9f781.png

3、a事务(客户端1) 回滚

ec54401f582d3639e8fb5c649004f1f0.png

4、b事务(客户端2) 再读该数据 和 2步不一致,脏读

6743edc90c5a2ebec4f9240acf965a47.png

读已提交----->不可重复读

设置当前会话隔离级别为读已提交

a9d6b1693bf9aea084fcfe1e10a43f71.png

SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;

1、a事务(客户端1) 修改 、未提交

1fbc9149a8e8f851eab4ae0c4edb8dea.png

2、b事务(客户端2) 读该数据

8831cc720341085552b7527695fa47df.png

3、a事务(客户端1) 提交

038a2561a5c2aa00a8ffe9e7504522a5.png

4、b事务(客户端2) 读该数据 , 不可重复读

83373894ddf043d0963f15738338bb64.png

可重复读----->幻读

设置当前会话隔离级别为可重复读

16991284a84e312bfed6dbf291954d27.png

SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;

1、a 事务(客户端1) 修改、未提交

13550c9b7c90e79bf9e1c00d64ee60c1.png

2、b 事务(客户端2) 读该数据

41e6a4de740ffb3b3cd50f2f9ed0c8c6.png

3、a 事务(客户端1) 提交

dffc8b9af9b31cbe170007f66a1fefec.png

4、b 事务(客户端2) 读该数据 和之前一样可重复读

2f2fe7ed0199a7ee5540ee2ebb438233.png

串行化

设置当前会话隔离级别为串行化

47ef500aadb29c29ca805ecd4113b93e.png

SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;

1、a 事务(客户端1) 读取id = 1的数据

5f0155a0f8b4096c2d615147103c28d3.png

2、b 事务(客户端2) 修改id = 1的数据,直接阻塞住

4da28ace6473fb4338676482d49f83fa.png

3、a 事务(客户端1) 提交

a7bbd3bc1eef9357044617874a32e03b.png

4、b 事务(客户端2) 获取行锁更新成功、串行执行

b5805723b1730098a461c84ef107b6c6.png

在InnoDB引擎下的的repeatable read (可重复复读)隔离级别下,快照读MVCC影响下,已经解决了幻读的问题

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

固定电话怎么认证显示公司名称?

在当今商业环境中,企业的联系方式,尤其是固定电话,不仅是与客户沟通的重要桥梁,也是展示企业专业形象的一部分。许多企业希望通过拨打固定电话联系客户时,能够对外显示公司名称,以此来增加电话的可信度和品…

使用 MMDetection 实现 Pascal VOC 数据集的目标检测项目练习(二) ubuntu的下载安装

首先,Linux系统是人工智能和深度学习首选系统。原因如下: 开放性和自由度:Linux 是一个开源操作系统,允许开发者自由修改和分发代码。这在开发和研究阶段非常有用,因为开发者可以轻松地访问和修改底层代码。社区支持:…

GetX的一些高级API

目录 前言 一、一些常用的API 二、局部状态组件 1.可选的全局设置和手动配置 2.局部状态组件 1.ValueBuilder 1.特点 2.基本用法 2.ObxValue 1.特点 2.基本用法 前言 这篇文章主要讲解GetX的一些高级API和一些有用的小组件。 一、一些常用的API GetX提供了一些高级…

做一个干电池的电量检测器03:数值拟合与电路仿真

首先在表格中进行详细的计算,整理出所需的数据。接着,我们运用MATLAB的强大功能对这些数据进行插值处理,生成了一个离散的数值数组。这个数组的每个数值都精确地对应着模数转换器(ADC)采样到的信号。通过这些数值&…

# linux从入门到精通-从基础学起,逐步提升,探索linux奥秘(十九)--mysql数据库基本操作

linux从入门到精通-从基础学起,逐步提升,探索linux奥秘(十九)–mysql数据库基本操作 一、MySQL的基本操作(1)(难点) 1、名词介绍 以Excel文件举例: 数据库&#xff1a…

关于我的编程语言——C/C++——第四篇(深入1)

(叠甲:如有侵权请联系,内容都是自己学习的总结,一定不全面,仅当互相交流(轻点骂)我也只是站在巨人肩膀上的一个小卡拉米,已老实,求放过) 字符类型介绍 char…

【python】OpenCV—Tracking(10.4)—Centroid

文章目录 1、任务描述2、人脸检测模型3、完整代码4、结果展示5、涉及到的库函数6、参考 1、任务描述 基于质心实现多目标(以人脸为例)跟踪 人脸检测采用深度学习的方法 核心步骤: 步骤#1:接受边界框坐标并计算质心 步骤#2&…

Unity核心笔记

1、认识模型的制作 1.建模 2.展UV 3.材质和纹理贴图 4.骨骼绑定 5.动画制作 总结 2、图片导入概述 1.Unity支持的图片格式 2.图片设置的6大部分 3、纹理类型设置 1.纹理类型主要是设置什么 2.参数讲解 4、纹理形状设置 1.纹理形状主要设置什么 2.参数讲解 5、纹理高级设置 …

(57)MATLAB使用迫零均衡器和MMSE均衡器的BPSK调制系统仿真

文章目录 前言一、仿真测试模型二、仿真代码三、仿真结果四、迫零均衡器和MMSE均衡器的实现1.均衡器的MATLAB实现2.均衡器的性能测试 总结 前言 本文给出仿真模型与MATLAB代码,分别使用具有ISI的三个不同传输特性的信道,仿真测试了使用迫零均衡器和MMSE…

[项目] C++基于多设计模式下的同步异步日志系统

[项目] C基于多设计模式下的同步&异步日志系统 文章目录 [项目] C基于多设计模式下的同步&异步日志系统日志系统1、项目介绍2、开发环境3、核心技术4、日志系统介绍4.1 日志系统的价值4.2 日志系统技术实现4.2.1 同步写日志4.2.2 异步写日志 5、相关技术知识5.1 不定参…

动态规划应该如何学习?

动态规划如何学习 参考灵神的视频和题解做的笔记(灵神YYDS,以后也都会用这套逻辑去思考) 枚举选哪个: 动态规划入门:从记忆化搜索到递推_哔哩哔哩_bilibili 746. 使用最小花费爬楼梯 - 力扣(LeetCode&a…

RK3588的QT交叉编译环境搭建

主要参考为RK3568或RK3288开发板创建交叉编译环境{采用amd64的ubuntu系统配置交叉编译arm64开发环境}(保姆级包括安装QT)超详细记录版_rk3568交叉编译-CSDN博客 先说一下,使用的Ubuntu20.04.5版本,qt源码用的5.14.2版本,交叉编译器使用RK3588…

专利生成穿刺demo

一、做原型 做原型?具体需求是啥?只有一个“帮助客户生成专利说明书”这样一个笼统的要求? 只有这些肯定是不能用来指导原型开发的。既然目前没有准确的需求,那就先看看现有的产品现状吧。 1.竞品分析 怎么开展哪?…

数字信号处理Python示例(3)生成三相正弦信号

文章目录 前言一、三相正弦信号的表示二、生成三相正弦信号的Python代码三、三相正弦信号的图示与分析四、生成幅度不相等的三相正弦信号的Python代码五、幅度不相等的三相正弦信号的图示与分析写在后面的话 前言 首先给出三相正弦信号的数学表达式,并给出生成三相…

【linux 多进程并发】0302 Linux下多进程模型的网络服务器架构设计,实时响应多客户端请求

0302 多进程网络服务器架构 ​专栏内容: postgresql使用入门基础手写数据库toadb并发编程 个人主页:我的主页 管理社区:开源数据库 座右铭:天行健,君子以自强不息;地势坤,君子以厚德载物. 一、概…

Linux云计算 |【第五阶段】CLOUD-DAY9

主要内容: Metrics资源利用率监控、存储卷管理(临时卷ConfitMap、EmptyDir、持久卷HostPath、NFS(PV/PVC)) 一、Metrics介绍 metrics是一个监控系统资源使用的插件,可以监控Node节点上的CPU、内存的使用率,或Pod对资…

Kafka 判断一个节点是否还活着有那两个条件?

大家好,我是锋哥。今天分享关于【Kafka 判断一个节点是否还活着有那两个条件?】面试题?希望对大家有帮助; Kafka 判断一个节点是否还活着有那两个条件? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在Ka…

PyQt5实战——多脚本集合包,UI以及工程布局(二)

个人博客:苏三有春的博客 系列往期: PyQt5实战——多脚本集合包,前言与环境配置(一) 布局 2.1 UI页面布局 整体框架分为分为三个部分,垂直分布。 第一个部分为功能选择按钮(如UTF-8转换&#…

Cpp::set map 的理解与使用(22)

文章目录 前言一、预备知识关联式容器键值对 二、set何为set?set的使用set的特点multiset 三、map何为map?map中的operator[ ]multimap 总结 前言 刚学完二叉搜索树,我们马上来感受一下直接与它相关的两个容器吧! 一、预备知识 关联式容器 在以往的 S…

PostgreSQL 学习笔记:PostgreSQL 主从复制

PostgreSQL 笔记:PostgreSQL 主从复制 博客地址:TMDOG 的博客 在现代应用程序中,数据库的高可用性和扩展性是至关重要的。PostgreSQL 提供了主从复制功能,可以在多个数据库实例之间复制数据,以实现冗余和负载均衡。本…