快速理解脏读,不可重复读,幻读

什么是脏读、不可重复读和幻读?产生原因是什么?有什么解决办法? 文章结合示例介绍了脏读、不可重复读、幻读的出现原因和影响,并引入拓展了MVCC、当前读、快照读、间隙锁等概念,通俗易懂 阅读详情

介绍

要聊事务,不可避免的要提到数据库事务的四大特性:ACID

  • atomic
  • consistence
  • isolation
  • durability

先放一个表格,看看4个隔离级别会出现的各种问题,网上的解释一大堆。看完后还是一脸懵逼,感觉懂了,又好像没懂。因为没有具体的演示例子,索性自己尝试复现这几个问题。

√ 为会发生,×为不会发生:

隔离级别脏读不可重复读幻读
read uncommitted(未提交读)√√√
read committed(提交读)×√√
repeatable read(可重复读)××√
serialization(可串行化)×××

再总结mysql 的常用命令(下面会用到):

命令含义
select version()查看MySQL版本
SELECT @@tx_isolation查看MySQL隔离级别
set session transaction isolation level 隔离级别会话层面设置隔离级别
start transaction开启事务
commit提交事务
rollback回滚事务

演示

首先建立如下表:

CREATE TABLE `account` (
 `id` int(2) NOT NULL AUTO_INCREMENT,
 `name` varchar(10) DEFAULT NULL,
 `balance` int(3) DEFAULT '0',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8mb4;

用Navicat(其他工具也行)开2个查询的tab页,表示2个会话
在这里插入图片描述

首先,在2个Tab页面分别执行SELECT @@tx_isolation,输出都是REPEATABLE-READ,表明MySQL默认隔离级别为REPEATABLE-READ(可重复)读。

*脏读

表中的数据如下,设置隔离级别为未提交读
在这里插入图片描述

时间客户端A客户端B
T1set session transaction isolation level read uncommitted;
start transaction(开启事务);
update account set balance = balance+1000 where id = 1;
select * from account where id = 1;
设置为未提交读,给张三账号+1000,输出为2000
T2set session transaction isolation level read uncommitted;
start transaction;
select * from account where id = 1;
查询余额输出为2000
T3rollback
T4commit
T5select * from account where id = 1;
查询余额输出为1000

----->举个例子概述一下这个过程,财务给张三发了1000元的工资,然后张三查询自己的账户,果然多了1000元,变成了2000元,结果财务操作过程有误,事务回滚。当张三再查账户时,却发现账户只有1000元。

脏读就是指当事务A对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务B也访问这个数据,然后使用了这个数据。

----->再举一例,表中的数据如下:
在这里插入图片描述

时间客户端A客户端B
T1set session transaction isolation level read uncommitted;
start transaction;
update account set balance = balance-1000 where id = 1;
update account set balance = balance+1000 where id = 2;
T2set session transaction isolation level read uncommitted;
start transaction;
select balance from account where id = 2;
update account set balance = balance -1000 where id = 2;
更新语句被阻塞
T3rollback
T4commit

执行完成,数据库中的数据如下
在这里插入图片描述
解释如下:

时间解释
T11给2转账1000
T22的余额够1000,购买1000元商品,更新语句被阻塞
T31回滚,1的余额变成1000,2的余额变成0
T42成功扣款,余额为0-1000=-1000

如此便出故障了!

*不可重复读

表中的数据如下,设置隔离级别为提交读
在这里插入图片描述

时间客户端A客户端B
T1set session transaction isolation level read committed;
start transaction;
select * from account where id = 2;
查询出余额输出为0;
T2set session transaction isolation level read committed;
start transaction;
update account set balance = balance + 1000 where id = 2;
select * from account where id = 2;
commit;
查询余额输出1000
T3select * from account where id = 2;
commit;
查询余额输出1000

不可重复读是指在事务1内,读取了一个数据,事务1还没有结束时,事务2也访问了这个数据,修改了这个数据,并提交。紧接着,事务1又读这个数据。由于事务2的修改,那么事务1两次读到的的数据可能是不一样的,因此称为是不可重复读。

当然你可以在T2时间段客户端B修改完id=2的账户余额但没有commit的时候,在客户端A查询id=2的账户余额,发现账户余额为0,可以证明提交读这个隔离级别不会发生脏读。

现在用上面的例子看一下可重复读是个什么过程?

表中的数据如下,设置隔离级别为可重复读
在这里插入图片描述

时间客户端A客户端B
T1set session transaction isolation level repeatable read;
start transaction;
select * from account where id = 2;
查询余额输出为0;
T2set session transaction isolation level repeatable read;
start transaction;
update account set balance = balance + 1000 where id = 2;
select * from account where id = 2;
commit;
查询余额输出1000
T3select * from account where id = 2;
commit;
查询余额输出0

仔细看这个例子和上面的例子在T3时间段的输出,理解了什么叫可重复读了吧?当我们将当前会话的隔离级别设置为可重复读的时候,当前会话可以重复读,就是每次读取的结果集都相同,而不管其他事务有没有提交。
----------但是在可重复读的隔离级别上,会产生幻读的问题。

*幻读

表中的数据如下,设置隔离级别为可重复读
在这里插入图片描述
先上一段《高性能MySQL》对于幻读的解释

所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行。InnoDB存储引擎通过多版本并发控制(MVCC)解决了幻读的问题。

用大白话解释一下,就是事务1查询id<10的记录时,返回了2条记录,接着事务2插入了一条id为3的记录,并提交。接着事务1查询id<10的记录时,返回了3条记录,说好的可重复读呢?结果却多了一条数据。

MySQL通过MVCC解决了这种情况下的幻读,我们可以验证一下

时间客户端A客户端B
T1set session transaction isolation level repeatable read;
start transaction;
select count(*) from account where id <=10;
输出2;
T2set session transaction isolation level repeatable read;
start transaction;
insert into account(id,name,balance) values(“3”,“王五”,“0”) ;
select count(*) from account where id <=10;
commit;
输出3
T3select count(*) from account where id <=10;
commit;
输出2

这种情况下的幻读被解决了,再举一例,表中的数据如下
在这里插入图片描述

时间客户端A客户端B
T1set session transaction isolation level repeatable read;
start transaction;
select count(*) from account where id =3;
输出0;
T2set session transaction isolation level repeatable read;
start transaction;
insert into account(id,name,balance) values(“3”,“王五”,“0”) ;
commit;
T3insert into account(id,name,balance) values(“3”,“王五”,“0”);
;主键重复,插入失败
T4select count(*) from account where id =3;
输出0;
T5rollback;

select 某记录是否存在,不存在,准备插入此记录,但执行 insert 时发现此记录已存在,无法插入,这个就有问题了。

很多人容易搞混不可重复读和幻读,确实这两者有些相似。但不可重复读重点在于update和delete,而幻读的重点在于insert。

注意:不可重复读和幻读的区别是:前者是指读到了已经提交的事务的更改数据(修改或删除),后者是指读到了其他已经提交事务的新增数据。
对于这两种问题解决采用不同的办法,防止读到更改数据,只需对操作的数据添加行级锁,防止操作中的数据发生变化;而防止读到新增数据,往往需要添加表级锁,将整张表锁定,防止新增数据(oracle采用多版本数据的方式实现)。

当隔离级别设置为可串行化,强制事务串行执行,避免了前面说的幻读的问题。

脏读、幻读、不可重复读产生的原因及解决方案 在平时操作数据库时,尤其是在并发场景下,常常会遇到一些问题,比如脏读、幻读、不可重复读,本篇我将对这几个问题产生的原因进行分析并给出解决办法 阅读详情

相关推荐

【点云可视化】自制ply文件并使用open3d可视化点云

使用open3d可视化点云,需要将点云制作为ply文件传入函数中。 安装open3d 直接使用pip安装 pip install open3d ply文件 ply文件的结构为:文件头+数据内容,文件头从 ply 一行开始,到 end_header 为止,里面定义了此 ply文件中数据的组织形式,包括数据类型和个数。后面是点云的坐标信息及每个点的颜色属性的,参考自 如下为具有5个点的点云,end_header后每一行表示一个点的x,y,z,R,G,B信息 ply format ascii 1.0 comme

这个人很蓝 1万+

脏读幻读和不可重复读 数据库锁 隔离机制

一、脏读、不可重复读、幻读1、脏读:脏读就是指当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。 例如: 张三的工资为5000,事务A中把他的工资改为8000,但事务A尚未提交。 与此同时, 事务B正在读取张三的工资,读取到张三的工资为8000。 随后, 事务A发生异常,而回滚了事务。张三的工资又回滚为5000。 最后, 事务B读取到的张三工资为8000的数据即为脏数据,事务B做了一次脏读。2、不可重复读:是指在一个事务内,多

song854601134的博客 6万+

EnlightenGAN训练复现记录

记录EnlightenGAN过程中的问题和解决方式。提示:以下是本篇文章正文内容,下面案例可供参考。

L_27N113E的博客 3845

一文详解脏读、不可重复读、幻读

MySQL 是支持多事务并发执行的。否则来一个事务处理一个请求,处理一个人请求的时候,其它事务都等着,那估计都没人敢用MySQL作为数据库,因为用户体验太差,估计都要砸键盘了。 既然事务可以并发操作,这里就有一些问题:一个事务在写数据的时候,另一个事务要读这行数据,该怎么处理?一个事务在写数据,另一个数据也要写这行数据,又该怎么处理这个冲突? 这就是并发事务所产生的一些问题。具体来说就是:脏读、不可重复读和幻读。 一、概念说明 以下几个概念是事务隔离级别要实际解决的问题,所以需要搞清楚都是什么意思。 1、脏

weixin_41814871的博客 4万+

PowerPMAC配置EtherCAT设备

本文详细介绍了在PowerPMAC IDE环境下配置EtherCAT伺服电机的完整流程。主要内容包括:准备工作(连接硬件和获取ESI文件)、通过ESI管理器加载配置文件、网络扫描识别从站设备、变量映射(定义输入输出位置参数)、激活EtherCAT通讯(验证状态字和实际位置)以及相关参数说明。文章还概述了主站配置的8个方面和从站配置的7个选项,重点说明了PDO映射和变量分配机制,为伺服电机的EtherCAT通信配置提供了系统指导。

mahuliang321的博客 962

工业视觉降本300%实战:C# + 开源YOLO如何干掉Halcon/VisionPro?

在当前制造业普遍追求“降本增效”的大背景下,工业视觉检测系统作为产线的眼睛,其成本问题日益突出。通过该方案,我们成功帮助一家电子厂将单条产线的视觉检测成本从15万降低至不足5千(主要为工控机硬件成本),降本幅度超过95%,且系统稳定性经受住了6个月连续生产的考验。:C#负责“工程化”和“业务逻辑”,YOLO负责“智能算法”,二者结合,完美覆盖了工业视觉从算法到落地的全链路。的组合,构建一套高性能、低成本、易维护的工业视觉解决方案,并彻底替代昂贵的付费库。” 这是一个典型的误区。工业相机/USB相机。

2601_94871597的博客 428

【MySQL理论】脏读、不可重复读、幻读

文章目录1. 脏读(dirty read)脏读是指事务读取到其他事务未提交的数据2. 不可重复读(non-repeatable read)不可重复读是指在同一次事务中前后查询不一致的问题3. 幻读(phantom read)幻读是一次事务中前后数据量发生变化,用户产生不可预料的问题4. 总结5. 解决方法 1. 脏读(dirty read) 脏读是指事务读取到其他事务未提交的数据 例如:有事务A、B和一条记录:id为1,name为张三 B首先进行更新操作,将name的值由张三改为张老三,但还未提交事务 be

Hi there 1万+

C++ PCL点云处理实战专栏

工业级点云处理技术学习资源,涵盖电力、建筑、隧道等领域的实战案例。内容分为三阶段:代码原理(算法认知)、动态库(项目验证)和完整代码(定制开发)。

weixin_45196569的博客 1117

快速理解脏读、不可重复读和幻读

MySQL的InnoDB引擎是支持事务的,但是并发事务的处理又会带来以下问题: 脏读 不可重复度 幻读 一、脏读 脏读指事务A读取到了事务B更新了但是未提交的数据,然后事务B由于某种错误发生回滚,那么事务A读取到的就是脏数据。 具体的说,一个数据原本是干净的,但是事务B将它进行修改使得其不再干净,此时事务A读取到事务B修改后的数据,也就是脏数据,称为脏读,后来事务B由于良心发现又将数据回滚为最初的样子,而事务A不知道事务B进行了回滚操作,最终事务A读取到的是脏数据,称为脏读。 结论:读取未提交的数据!

郑皓云的博客 8586

RPA与旅游与酒店行业自动化实战案例

1. 背景介绍 1.1 旅游与酒店行业的挑战 旅游与酒店行业是一个高度竞争的市场,企业需要不断提高服务质量、降低成本、提高效率以保持竞争力。在这个过程中,企业面临着诸多挑战,如客户需求多样化、市场变化快速、人力资源成本高昂等。为了应对这些挑战,企业需要寻求新的技术手段来提高运营效率。

AI天才研究院 615

Qt/C++编写自定义控件49-飞机仪表盘

一、前言 飞行仪表是测定和表示飞机数据的工具,飞机中必不可少的一部分,飞行员根据飞行仪表表示的数据才能正确地做出判断。一般飞机仪表包括高度表+空速表+垂直速率表+姿态仪+航向指示表+转弯协调表。 这次要绘制的是其中的姿势仪,显示飞机相对于地平线的姿态,看姿态仪,飞行员能判断飞机姿态为偏左偏右,及偏上和偏下。姿态仪作用原理为一高度旋转的陀螺,不论飞机的姿态如何变化,此陀螺的定轴性在空间保持相同,因而...

Qt/C++视频监控/推流/物联网/大屏系统/自定义控件/UI定制/输入法 7023

快速理解脏读、不可重复读、幻读

                             快速理解脏读、不可重复读、幻读?   理解这三种由于并发访问导致的数据读取问题,再理解事务隔离级别就简单多了。   【1】脏读(读取未提交数据) ...

iQian²的博客 168

从 SAP ABAP 到 S/4HANA,SAML 2.0 单点登录到底是怎么跑起来的

在很多 SAP 项目里,SSO 不是一个锦上添花的功能,而是系统能不能顺利上线的基本门槛。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 1048

快速理解脏读、不可重复读、幻读和MVCC

理解这三种由于并发访问导致的数据读取问题,再理解事务隔离级别就简单多了。脏读(读取未提交数据)A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行回滚操作,那么...

互扯程序的博客 2561

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

【数据库】快速理解脏读、不可重复读、幻读

快速理解脏读、不可重复读、幻读? 理解这三种由于并发访问导致的数据读取问题,再理解事务隔离级别就简单多了。 【1】脏读(读取未提交数据) A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行回滚操作,那么A事务读取到的数据就是脏数据。就好像原本的数据比较干净、纯粹,此时由于B事务更改了它,这个数据变得不再纯粹。这个...

阳阳的博客 11万+

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

【MySQL】快速理解脏读、不可重复读、幻读

脏读指一个事务读取到另一个事务未提交的修改数据,若后者发生回滚,前者读取的数据即为无效的“脏数据”。

大白的成长之路 1978

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

快速理解 脏读、不可重复读、幻读(解决方法)

文章目录脏读【读取数据未提交】不可重复读【前后多次读取,数据内容不一致】幻读【前后多次读取,数据总量不一致】数据库事务隔离级别未提交读读已提交 Read Committed可重复读 Repeatable Read可串行化 Serializable 脏读【读取数据未提交】 一个事务读取另外一个事务未提交的更新事务。 事务1 事务2 select age from table1 whe...

wangrui1605的博客 1782

java 幻读 脏读_快速理解脏读、不可重复读、幻读

1、脏读 是指A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行回滚,那么A事务读取到的数据就是脏数据,一般发生在并发或多用户操作同一数据库信息时产生的。脏读举例说明:现有A、B两位同学,A同学账户有2000元, 两位同学同时操作A账户1560499745(1).png2、不可重复读 是指A事务读取了B事务已经提交的更改数据,假如A在取款过程中,B往该账户转账100,A再次读取的余额发...

weixin_30827827的博客 908

【数据库】快速理解脏读、不可重复读、幻读?

快速理解脏读、不可重复读、幻读? 理解这三种由于并发访问导致的数据读取问题,再理解事务隔离级别就简单多了。 【1】脏读(读取未提交数据) A事务读取B事务尚未提交的数据,此时如果B事务发生错误并执行回滚操作,那么A事务读取到的数据就是脏数据。就好像原本的数据比较干净、纯粹,此时由于B事务更改了它,这个数据变得不再纯粹。这个时候A事务立即读取了这个脏数据,但事务B良心发现,又用回滚把数据恢复成原来干净、纯粹的样子,而事务A却什么都不知道,最终结果就是事务A读取了此次的脏数据,称为脏读。 这种情况常发

zero123_的博客 176
上一篇: Netty编解码框架分析
下一篇: mysql数据备份
zhg_vincent
博客等级 码龄12年 93粉丝 45原创
评论 21
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值