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 (--自增IDid 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影响下,已经解决了幻读的问题

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

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

相关文章

数字后端零基础入门系列 | Innovus零基础LAB学习Day9

Module 16 Wire Editing 这个章节的学习目标是学习如何在innovus中手工画线,切断一根线,换孔,更改一条net shape的layer和width等等。这个技能是每个数字IC后端工程师必须具备的。因为项目后期都需要这些技能来修复DRC和做一些手工custom走线…

前后端交互通用排序策略

目录 排序场景 排序实现思路 1. 静态代码排序实现 2.数据库驱动排序实现 3. 基于Java反射的动态排序实现 通用排序工具 SortListUtil 结语 排序场景 在面向前端数据展示的应用场景中,我们旨在实现一个更加灵活的排序机制,该机制能够支持对从后端传递…

前端入门一之CSS知识详解

前言 CSS是前端三件套之一,在MarkDown中也完美兼容这些语法;这篇文章是本人大一学习前端的笔记;欢迎点赞 收藏 关注,本人将会持续更新。 文章目录 Emmet语法:CSS基本语法:css语法结构只有3种&#xff1a…

leetcode | 88. 合并两个有序数组

题目描述 88. 合并两个有序数组 分析 题目不允许更改nums1的长度,要求原地更改。 题目其实不难,如果记住可以从后往前合并的解法,但是正向遍历的问题是什么呢? ——元素覆盖。那为什么负向遍历就不会有这个问题呢?…

跳蚤市场之商品发布功能

一 商品类别和小类的联动 以下是一个示例代码&#xff0c;展示了如何实现商品类别中大类和小类的联动。 商品大类选择框、小类选择框 的设计 html部分 <form id"category-form"><label for"major-category">大类&#xff1a;</label&g…

OpenAI 发布了新的事实性基准——SimpleQA

SimpleQA 简介 名为 SimpleQA 的事实性基准&#xff0c;用于衡量语言模型回答简短的事实性问题的能力。 人工智能领域的一个悬而未决的问题是如何训练模型&#xff0c;使其产生符合事实的回答。 目前的语言模型有时会产生错误的输出或没有证据证明的答案&#xff0c;这个问题…

Android camera2

一、序言 为了对阶段性的知识积累、方便以后调查问题&#xff0c;特做此文档&#xff01; 将以camera app 使用camera2 api进行分析。 (1)、打开相机 openCamera (2)、创建会话 createCaptureSession (3)、开始预览 setRepeatingRequest (4)、停止预览 stopRepeating (5)、关闭…

Javascript属性遮蔽问题

先了解一下Object.defineProperty()方法 Object.defineProperty() 静态方法会直接在一个对象上定义一个新属性&#xff0c;或修改其现有属性&#xff0c;并返回此对象。 //obj&#xff1a;要定义的对象 //prop&#xff1a;一个字符串或 Symbol&#xff0c;指定了要定义或修改…

vue3项目history模式部署404处理,使用 historyApiFallback 中间件支持单页面应用路由

vue3项目history模式部署404处理&#xff0c;使用 historyApiFallback 中间件支持单页面应用路由 在现代的 web 开发中&#xff0c;单页面应用&#xff08;SPA&#xff09;变得越来越流行。这类应用通常依赖于客户端路由来提供流畅的用户体验&#xff0c;但在服务器端&#xf…

【vim文本编辑器gcc编译器gdb调试器】

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 一、vimvim安装vim常用快捷键vim使用vimtutor zh文档 二、gcc编译器安装gcc工具编译源代码 三、gdb调试器gdb安装gdb常用指令gdb简单上手使用gdb的单步调试功能 总结…

企业数字化转型的架构治理策略:核心问题、深度分析与优化路径

在当今的商业环境中&#xff0c;企业数字化转型已成为实现可持续发展、增强竞争力的战略选择。企业架构治理&#xff08;Enterprise Architecture Governance Capability, EAGC&#xff09;在数字化转型中扮演着保障架构一致性、提升变革效能的关键角色。本指南深入解析了如何通…

基于springboot+vue实现的农产品物流系统

基于springbootvue实现的农产品物流系统 &#xff08;源码L文ppt&#xff09;4-107 摘 要 随着现代信息技术的迅猛发展&#xff0c;农产品物流系统应运而生&#xff0c;成为连接生产者与消费者的重要桥梁。该系统采用java语言&#xff0c; Spring Boot框架&#xff0c;结合My…

基于uniapp和java的电动车智能充电系统软件平台的设计

文章目录 项目介绍具体实现截图技术介绍mvc设计模式小程序框架以及目录结构介绍错误处理和异常处理java类核心代码部分展示详细视频演示源码获取 项目介绍 对电动车智能充电系统进行设计和开发。通过使用本系统可有效地减少运营成本&#xff0c;提高管理效率。 根据近年来社会…

Jmeter命令监控CPU等指标

JMeter 命令行执行脚本得到的报告中&#xff0c;是没有CPU、内存使用率等监控数据的&#xff0c;但是可以使用JMeter插件帮忙。 一、下载jmeter-plugins-manager.jar 下载后将文件放到jmeter安装包lib/ext目录下。打开Jmeter》菜单栏》选项》Plugins Manager 二、安装PerfMon…

ubuntu20.04 加固方案-检查是否设置登录超时

一、编辑/etc/profile配置文件 打开终端。 使用文本编辑器&#xff08;如vim&#xff09;编辑/etc/profile 文件。 vi /etc/profile 二、添加配置参数 在打开的配置文件中&#xff0c;如图位置添加如下参数&#xff1a; TMOUT1800 export TMOUT三、保存并退出 在vim编辑器…

HarmonyOS使用arkTS拉起指定第三方应用程序

HarmonyOS使用arkTS拉起指定第三方应用程序 前言代码及说明bundleName获取abilityName获取 前言 本篇只说采用startAbility方式拉起第三方应用&#xff0c;需要用到两个必备的参数bundleName&#xff0c;abilityName&#xff0c;本篇就介绍如何获取参数… 代码及说明 bundle…

32位汇编——通用寄存器

通用寄存器 什么是寄存器呢&#xff1f; 计算机在三个地方可以存储数据&#xff0c;第一个是把数据存到CPU中&#xff0c;第二个把数据存到内存中&#xff0c;第三个把数据存到硬盘上。 那这个所谓的寄存器&#xff0c;就是CPU中用来存储数据的地方。那这个寄存器有多大呢&a…

江协科技STM32学习- P35 硬件I2C读写MPU6050

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

【大数据学习 | HBASE】habse的表结构

在使用的时候hbase就是一个普通的表&#xff0c;但是hbase是一个列式存储的表结构&#xff0c;与我们常用的mysql等关系型数据库的存储方式不同&#xff0c;mysql中的所有列的数据是按照行级别进行存储的&#xff0c;查询数据要整个一行查询出来&#xff0c;不想要的字段也需要…