mysql事务隔离级别详细讲解
mysql事务讲解
MySQL事务处理(TransAction)
大家好,我是一名热爱研究技术并且喜欢自己亲手实践的博主。
工作这么多年,一直没有深入理解MySQL的事务,因为最近也在面试,准备复习mysql的相关知识,帮自己回顾总结一下,其次就是想把这篇博客分享给大家,如果你才刚刚开始学习mysql,那么希望这篇博客对你有一点启发;亦或者你早已是一个mysql老油条,这篇博客也会使你对mysql事务有一个更深的印象。
话不多说,直接开始上强度…
首先,什么是事务呢?
事务就是由单独单元的一个或多个sql语句组成,在这个单元中,每个sql语句都是相互依赖的。而整个单独单元是作为一个不可分割的整体存在,类似于物理当中的原子(一种不可分割的最小单位)。
往通俗的讲就是,事务就是一个整体,里面的内容要么都执行成功,要么都不成功。不可能存在部分执行成功而部分执行不成功的情况。
就是说如果单元中某条sql语句一旦执行失败或者产生错误,那么整个单元将会回滚(返回最初状态)。所有受到影响的数据将返回到事务开始之前的状态,但是如果单元中的所有sql语句都执行成功的话,那么该事务也就被顺利执行。
大家都知道,我们的数据都是通过各种不同技术的存储引擎来引导存储的,不同的存储引擎,都有各自的特点。在mysql中,常见的存储引擎有innodb、myisam,memory等。其中innodb支持事务(transaction),而myisam,memory等不支持事务。
可以通过show engines;语句来查看mysql支持的存储引擎
一、事务的四个特性(ACID)【面试常考项】
原子性(Atomicity):指事务是一个不可分割的最小工作单位,事务中的操作只有都发生和都不发生两种情况
一致性(Consistency):事务必须使数据库从一个一致状态变换到另外一个一致状态,举一个例子,李二给王五转账50元,其事务就是让李二账户上减去50元,王五账户上加上50元;一致性是指其他事务看到的情况是要么李二还没有给王五转账的状态,要么王五已经成功接收到李二的50元转账。而对于李二少了50元,王五还没加上50元这个中间状态是不可见的。
隔离性(Isolation):一个事务的执行不能被其他事务干扰,即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(Durability):一个事务一旦提交成功,它对数据库中数据的改变将是永久性的,接下来的其他操作或故障不应对其有任何影响。
二、事务的分类
事务分为隐式事务和显式事务两种。我们的DML语句(insert、update、delete)就是隐式事务。
隐式事务:该事务没有明显的开启和结束标记,它们都具有自动提交事务的功能;不妨思考一下,update语句修改数据时,是不是对表中数据进行改变了,它的本质其实就相当于一个事务。
举一个例子:张三同学买了一个csdn定制保温杯花了99元,是不是就是update语句对字段name为张三的同学的余额balance进行减99元的处理呢?
显示事务:该事务具有明显的开启和结束标记;也是本文重点要讲的东西。使用显式事务的前提是你得先把自动提交事务的功能给禁用。禁用自动提交功能就是设置autocommit变量值为0(0:禁用 1:开启)
先查看一下当前的autocommit变量值,发现当前处于开启自动提交事务的状态
禁用自动提交事务的功能并查看当前状态
三、开启事务的步骤
假设t_account表已经存在
#步骤一:开启事务(可选)
start transaction;
#步骤二:编写事务中的sql语句(insert、update、delete)
#这里实现一下"李二给王五转账"的事务过程
update t_account set balance = 50 where vname = "李二";
update t_account set balance = 130 where vname = "王五";
#步骤三:结束事务
commit; #提交事务
#rollback;#回滚事务:就是事务不执行,回滚到事务执行前的状态
四、事务并发时出现的问题
但是呢,因为某一刻不可能总只有一个事务在运行,可能出现A在操作t_account表中的数据,B也同样在操作t_account表,那么就会出现并发问题,对于同时运行的多个事务,当这些事务访问数据库中相同的数据时,如果没有采用必要的隔离机制,就会发生以下各种并发问题。
🌴脏读:对于两个事务T1,T2,T1读取了已经被T2更新但还没有被提交的字段之后,若T2回滚,T1读取的内容就是临时且无效的
🌴不可重复读 :对于两个事务T1,T2,T1读取了一个字段,然后T2更新了该字段之后,T1在读取同一个字段,值就不同了
🌴 幻读:对于两个事务T1,T2,T1在A表中读取了一个字段,然后T2又在A表中插入了一些新的数据时,T1再读取该表时,就会发现神不知鬼不觉的多出几行了…
所以,为了避免以上出现的各种并发问题,我们就必然要采取一些手段。mysql数据库系统提供了四种事务的隔离级别,用来隔离并发运行各个事务,使得它们相互不受影响,这就是数据库事务的隔离性。
五、事务的隔离级别
mysql中的四种事务隔离级别如下:
1. read uncommitted(读未提交数据):允许事务读取未被其他事务提交的变更。(脏读、不可重复读和幻读的问题都会出现)。
2. read committed(读已提交数据):只允许事务读取已经被其他事务提交的变更。(可以避免脏读,但不可重复读和幻读的问题仍然可能出现)
3.repeatable read(可重复读):确保事务可以多次从一个字段中读取相同的值,在这个事务持续期间,禁止其他事务对这个字段进行更新(update)。(可以避免脏读和不可重复读,但幻读仍然存在)
4. serializable(串行化):确保事务可以从一个表中读取相同的行,在这个事务持续期间,禁止其他事务对该表执行插入、更新和删除操作,所有并发问题都可避免,但性能十分低下(因为你不完成就都不可以弄,效率太低)
了解: oracle支持两种事务隔离级别:read committed、serializable。
oracle默认的事务隔离级别是:read committed。
mysql的默认事务隔离级别是:repeatable read。
一个事务与其他事务隔离的程度称为隔离级别。数据库规定了多种事务隔离级别,不同隔离级别对应不同的干扰程度,隔离级别越高,数据一致性就越好,但并发性就越差。
这里通过一个例子向大家简单介绍一下并发:
一个人🚶 在边开车🚕 边打电话📞,首先,人只有一个大脑(cpu),但是在同一时刻他却在执行2件事情,其实内部就是靠他的大脑在不断的切换执行,之所以人民警察👮 不允许司机开车时打电话,就是怕人脑在那一瞬间切换不过来,从而导致交通事故的发生,并发和这个例子是差不多的意思。但在这里,电脑cpu可比人脑快多了,所以出错的概率也相对来说小很多。
接一下,演示一下在几种不同的事务隔离级别下所发生的不同情况😶 。
在演示之前呢,还需要知道如何查看和设置事务的隔离级别
查看当前的事务隔离级别通过 tx_isolation变量或者transaction_isolation(版本8.0以上使用);
语法:select @@tx_isolation;
注意:在mysql8.0之后,就已经抛弃了tx_isolation变量了,而是用 transaction_isolation变量代替了。
语法:select @@transaction_isolation;
#设置当前mysql连接的隔离级别:
set session transaction isolation level read uncommitted;
#设置数据库系统的全局的隔离级别:
set global transaction isolation level read uncommitted;
注意:当前mysql连接的隔离级别和mysql全局的隔离级别的区别是什么?
如果只设置当前的隔离级别(即当前打开的navacat窗口),也就是session,那么另外一个并发的“mysqy程序”的隔离级别不会受到当前连接的影响,而是保持默认的repeatable read。
但是如果是设置全局的事务隔离级别,则整个mysql数据库(包括所有打开的mysql程序连接)的隔离级别都会随之改变,除非服务器重启,不然就不会恢复默认了。
两者仅仅一词之差,其效果却天差地别。
好,了解完如何设置事务的隔离级别之后,下面将正式进入…
这里的讲解主要是为了知道在并发的环境下,不同的事务隔离级别所表现出的不同特点,那么自然还是要先模拟一下并发环境
这里打开两个独立的mysql数据库连接(mysql程序1和mysql程序2),用来模拟并发环境
事务T1
事务T2
同志们打起精神认真看啊!!
read uncommitted(读未提交)
首先,我们需要先将两个会话的事务隔离级别都设置为read uncommitted;语句如下:
#事务T1
#设置隔离级别,读未提交
set session transaction isolation level read UNCOMMITTED;
select @@tx_isolation;
#select @@transaction_isolation;(8.0以后版本用这个)
#禁止自动提交事务
set autocommit = 0
SELECT @@autocommit;
#事务T2
#设置隔离级别,读未提交
set session transaction isolation level read UNCOMMITTED;
select @@tx_isolation;
#select @@transaction_isolation;(8.0以后版本用这个)
#禁止自动提交事务
set autocommit = 0
SELECT @@autocommit;
此图为t_student的表数据,以下代码,通过user_id为12的这条数据作验证
read uncommitted可以读到其他事务还没提交的变更,这里举例:事务T2对t_student表中的数据进行更改,看事务1多次查询的结果是否一致。
操作步骤:
1.执行事务T1中的语句
2.执行事务T2中的语句(千万不要提交)
3.执行事务T1中的语句
步骤1执行结果
步骤2执行完,步骤3执行结果
可以看到事务T2修改了t_stundent表中的age字段,但是事务T1两次执行的结果不一样,后一次查询和表中数据也不一致(因为事务T2未提交),所以这就是读未提交的特点,不管你事务是否提交,只要数据发生改变我就可以察觉到。
未解决的问题:
脏读:回滚T2,此时第二次T1的查询就是无效的
不可重复读:两次读取的结果不一致
幻读:可以把T2的update换成insert语句,会发现第二次事务T1读取的数据多了几行
接下来要看的是read committed(读已提交)
read committed(读已提交)
测试前一定要记住设置事务的隔离级别为read committed;并且禁用自动提交事务【设置autocommit为0】(后面的每个测试都是一样的)
# 设置事务隔离级别为read committed
set session transaction isolation level read committed;
# 禁用自动提交事务功能
set autocommit = 0;
#接下来的 repeatable read 隔离级别和 serializable 隔离级别也是同样的操作
细节:T2执行udate之后,控制执行的返回结果是修改行数是0,只有提交之后,修改的结果才会大于1(当前条件下数据确实是存在的)
可以看到事务T2修改了t_stundent表中的age字段,但是事务T1两次执行的结果仍然一样,两次查询和表中数据一致(因为事务T2未提交),所以这就是读已提交的特点,只有事务已经提交,其他事务才可以察觉到。
未解决的问题:
脏读:已解决,因为脏读是能读取未提交的数据,但此时并未读取到T2未提交的数据
不可重复读:两次读取的结果不一致(即T2前后,T1查询的结果不一致)
幻读:可以把T2的update换成insert语句,会发现第二次事务T1读取的数据多了几行
repeatable read(可重复读)
该隔离级别为mysql的默认隔离级别;它对某字段进行操作时,其他事务禁止操作该字段。它总能保持你读取的数据是一致的。
细节:T2执行udate之后,控制执行的返回结果是修改行数是0,只有提交之后,修改的结果才会大于1(当前条件下数据确实是存在的)
事务T2操作t_student表时,事务T1是无权对t_account表进行任何操作,如果强行操作的话,就会一直等待,直到T
事务T2提交或者回滚(一直等待会报错 (“ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction”;翻译为“超过锁定等待超时;尝试重新启动事务”)),这里是因为事务T2update语句会默认添加独占锁,如果其他事务对持有独占锁的记录进行修改时,就会被阻塞。
脏读:已解决,因为脏读是能读取未提交的数据,但此时并未读取到T2未提交的数据
不可重复读:已解决,两次读取的结果一致(即T2回滚活提交前后,T1查询的结果一致)
幻读:可以把T2的update换成insert语句,会发现第二次事务T1读取的数据多了几行
serializable(串行化)
该隔离模式下执行的事务在对某表进行操作期间,禁止其他所有事务对该表进行任何操作
如果强行操作也会报错(和可重复读那个错误一致),因为serializable用的相对比较少,这里就不做演示了。同学们理解了就好。
事务的保存点(回滚点)
回滚点表示的就是使事务回滚到指定回滚点
语法: savepoint 节点名称 ;
注意:保存点只允许搭配rollback回滚来使用,不能和commit一起使用
已知表t_student存在,其数据如下(第一次查询就是全量数据):
代码举例如下:
#禁用自动提交事务
set autocommit = 0;#开启事务
start transaction;#删除id为2的记录
delete from t_stu where id = 2;#设置保存点名为AA
savepoint AA;#删除id为3的记录
delete from t_stu where id = 3;#回滚到AA保存点处
rollback to AA;
运行结果如下:
可以看到user_id为3的数据被删除了,而user_id为4的还在,就是因为事务回滚到了AA处,所以user_id为3的那条记录被回滚掉了。
原文链接:https://blog.csdn.net/qq_56880706/article/details/122653735,本文是在作业的基础上自己进行了操作,并赋上了自己的心德,如有不正确支出,望各位大佬评论尽快修改,避免耽误其他同学
相关文章:

mysql事务隔离级别详细讲解
mysql事务讲解 MySQL事务处理(TransAction) 大家好,我是一名热爱研究技术并且喜欢自己亲手实践的博主。 工作这么多年,一直没有深入理解MySQL的事务,因为最近也在面试,准备复习mysql的相关知识࿰…...

如何利用 EMC 模型解决能源服务提供商的瓶颈
01. 什么是合同能源管理? 合同能源管理(EMC-Energy Management Contract) 是一种新型的市场化节能机制,其实质就是以减少的能源费用来支付节能项目全部成本的节能投资方式。:节能服务公司与用能单位以契约形式约定节能项目的节能目标,节能服…...
C#--StringComparison枚举值解析
StringComparison 枚举值是在 C# 中用于指定字符串比较规则的枚举类型。它提供了不同的选项,以满足不同的比较需求。下面是 StringComparison 枚举值的解析: StringComparison.CurrentCulture:使用当前线程的区域设置(Culture&am…...

adb对安卓app进行抓包(ip连接设备)
adb对安卓app进行抓包(ip连接设备) 一,首先将安卓设备的开发者模式打开,提示允许adb调试 二,自己的笔记本要和安卓设备在同一个网段下(同连一个WiFi就可以了) 三,在笔记本上根据i…...

【EI复现】考虑区域多能源系统集群协同优化的联合需求侧响应模型(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...

日常BUG —— Java判空注解
😜作 者:是江迪呀✒️本文关键词:日常BUG、BUG、问题分析☀️每日 一言 :存在错误说明你在进步! 一. 问题描述 问题一: 在使用Java自带的注解NotNull、NotEmpty、NotBlank时报错,…...

【基础类】—前端算法类
一、排序 1. 排序方法列表 2. 常见排序方法 快速排序选择排序希尔排序 二、堆栈、队列、链表 堆栈、队列、链表 三、递归 递归 四、波兰式和逆波兰式 理论源码...

中国信通院腾讯安全发布《2023数据安全治理与实践白皮书》
导读 腾讯科技(深圳)有限公司和中国信息通信研究院云计算与大数据研究所共同编制了本报告。本报告提出了覆盖组织保障、管理流程、技术体系的以风险为核心的数据安全治理体系,并选取了云场景、互娱、社交等场景,介绍相应场景下数据安全治理实践路线及主…...
linux下用脚本将目录内的文件分类到各自的创建年份(如2023)或年月份(如2023/202308)目录内
第一个if判断语句中判定只有是文件的时候才执行mv操作,并忽略一些特定 第二个if判断目录不存在时创建目录 最后mv文件到目录内 脚本执行前目录内容: 2022-01-file 2023-02-file 脚本执行后目录内容: 2022 |2022-01-file 2023 |2023-02-file …...

新手如何快速学习单片机?
初步确定学习目标:是学习简单便宜的51呢,还是学习简单但是性价比已经不算太高的,但是功能强大稳定可靠的avr,还是物美价廉的stm32,或者ARM9(可以跑系统了),再往上x86什么的如果是学8…...

【容器化】Oceanbase镜像构建及使用
通过该篇文章可以在国产X86-64或ARM架构上构建商业版oceanbase,只需要替换pkg安装包即可。下面截图主要以国产X86-64安装为例,作为操作截图: 镜像构建目录说明 pkg:用来存放安装包及脚本,抛出rpm其他是脚步,这些rpm包…...

软考第二章 信息技术发展
本章内容:软件硬件、网络、存储、新技术。 文章目录 2.1 信息技术及其发展2.1.1 计算机硬件2.1.2 计算机网络2.1.3 存储和数据库2.1.4 信息安全 2.2 新一代信息技术2.2.1 物联网2.2.2 云计算2.2.3 大数据2.2.4 区块链2.2.5 人工智能虚拟现实 2.1 信息技术及其发展 …...

【Unity每日一记】向量操作摄像机的移动(向量加减)
👨💻个人主页:元宇宙-秩沅 👨💻 hallo 欢迎 点赞👍 收藏⭐ 留言📝 加关注✅! 👨💻 本文由 秩沅 原创 👨💻 收录于专栏:uni…...

C++初阶之一篇文章教会你queue和priority_queue(理解使用和模拟实现)
queue和priority_queue(理解使用和模拟实现) 什么是queuequeue的使用1.queue构造函数2.empty()3.size()4.front()5.back();6.push7.emplace8.pop()9.swap queue模拟实现什么是priority_queuepriority_queue的使用1.priority_queue构造函数1.1 模板参数 C…...

性能场景和性能需求指标
目录 一 性能场景 1、基准性能场景 2、容量性能场景 3、稳定性性能场景 4、异常性能场景 二 性能需求指标 1、业务指标 2、技术指标 2.1 时间指标 RT 2.2 容量指标 TPS 2.3 资源利用率 3、指标之间的关系 “TPS”与“响应时间” “用户数”与“TPS”与“压力工具中…...
Python学习 -- 常用函数与实例详解
在Python编程中,数据转换是一项关键任务,它允许我们在不同数据类型之间自由流动,从而提高代码的灵活性和效率。本篇博客将深入探讨常用的数据转换函数,并通过实际案例为你展示如何巧妙地在不同数据类型之间转换。 数据类型转换函…...

MySQL 账号权限
mysql 在安装好后,默认是没有远端管理账号。 一、账号管理 1. 查看账号列表 MySQL用户账号和信息存储在名为 mysql 的数据库中。一般不需要直接访问 mysql 数据库和表,但有时需要直接访问。例如,查看数据库所有用户账号列表时。 USE mysql; …...

[Mongodb 5.0]单机启动
安装完mongodb后,会自动生成下面两个目录(mongod.conf中设定的),用来存放日志和数据 /var/lib/mongo (数据目录) /var/log/mongodb (日志目录) 要启动一个单机版的mongodb,一般有两种方式: 第一种启动方式:直接使用…...

[HDLBits] Exams/m2014 q4b
Implement the following circuit: module top_module (input clk,input d, input ar, // asynchronous resetoutput q);always(posedge clk or posedge ar) beginif(ar)q<1b0;elseq<d;end endmodule...

数据结构入门:队列
目录 文章目录 前言 1.队列 1.1 队列的概念及结构 1.2 队列的实现 1.2.1 队列的定义 1.2.2队列的初始化 1.2.3 入队 1.2.4 判空 1.2.5 出队 1.2.6 队头队尾数据 1.2.7 队列长度 1.2.8 队列销毁 总结 前言 队列,作为一种重要的数据结构,在计算机科学中扮演…...

使用VSCode开发Django指南
使用VSCode开发Django指南 一、概述 Django 是一个高级 Python 框架,专为快速、安全和可扩展的 Web 开发而设计。Django 包含对 URL 路由、页面模板和数据处理的丰富支持。 本文将创建一个简单的 Django 应用,其中包含三个使用通用基本模板的页面。在此…...

Linux 文件类型,目录与路径,文件与目录管理
文件类型 后面的字符表示文件类型标志 普通文件:-(纯文本文件,二进制文件,数据格式文件) 如文本文件、图片、程序文件等。 目录文件:d(directory) 用来存放其他文件或子目录。 设备…...
前端倒计时误差!
提示:记录工作中遇到的需求及解决办法 文章目录 前言一、误差从何而来?二、五大解决方案1. 动态校准法(基础版)2. Web Worker 计时3. 服务器时间同步4. Performance API 高精度计时5. 页面可见性API优化三、生产环境最佳实践四、终极解决方案架构前言 前几天听说公司某个项…...
【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密
在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)
目录 1.TCP的连接管理机制(1)三次握手①握手过程②对握手过程的理解 (2)四次挥手(3)握手和挥手的触发(4)状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...
Auto-Coder使用GPT-4o完成:在用TabPFN这个模型构建一个预测未来3天涨跌的分类任务
通过akshare库,获取股票数据,并生成TabPFN这个模型 可以识别、处理的格式,写一个完整的预处理示例,并构建一个预测未来 3 天股价涨跌的分类任务 用TabPFN这个模型构建一个预测未来 3 天股价涨跌的分类任务,进行预测并输…...

Python实现prophet 理论及参数优化
文章目录 Prophet理论及模型参数介绍Python代码完整实现prophet 添加外部数据进行模型优化 之前初步学习prophet的时候,写过一篇简单实现,后期随着对该模型的深入研究,本次记录涉及到prophet 的公式以及参数调优,从公式可以更直观…...
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析
Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问(基础概念问题) 1. 请解释Spring框架的核心容器是什么?它在Spring中起到什么作用? Spring框架的核心容器是IoC容器&#…...

JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...