mysql事务隔离级别/脏读/不可重复读/幻读详解

一、四种事务隔离级别

1.1 read uncommitted 读未提交

即:事务A可以读取到事务B已修改但未提交的数据。

除非是文章阅读量,每次+1这种无关痛痒的场景,一般业务系统没有人会使用该事务隔离级别,标准实在太宽松了。

1.2 read committed 读已提交(简称RC)

即:事务A只能读取到事务B修改并已提交的数据。

这个级别相对要严格一些,至少是要等其它事务把变更提交到db,才能读取到,听上去蛮靠谱的。但是有些业务场景,比如会员系统中,如果要在一个事务中,多次读取用户身份,判断是否会员,如果刚开始读取到该用户是会员,做了一些逻辑处理,后面又读到用户不是会员了,这就有点崩溃,不知道如何继续。这种希望同1个事务中,关键数据不管读取多次次,结果都一样,RC级别就不行了。

1.3 repeatable read 可重复读

即:同一个事务中,多次读取某一行记录,始终是一样的值,不管在此期间,其它事务有没有修改过该数据(不论是否提交)。该级别解决了RC不可重复读的问题,但是存在幻读问题(幻读后面会详解)。

1.4 serializable 串行化

即:一个事务在修改其它数据时,如果有其它事务也想改,必须等前面的事务提交或回滚后,才能继续。最严格的级别,但是性能最低,也几乎没人用。

二、脏读/不可重复读/幻读
2.1 脏读

验证:

a. 找一个mysql环境,建一个测试表t_people,就2列 id ,name

b. 开二个mysql终端,连到db上,为方便讲解,这2个终端称为“终端1”、“终端2”,终端1里输入:

set session transaction isolation level read uncommitted;
start transaction;

即:设置当前会话的隔离级别为"读未提交"。

终端2里,输入:

start transaction;
update t_people set name=‘xxx‘ where id=1;

然后再回到“终端1”,执行

select id,name from t_people where id=1;

可以看到,读取到了未提交的脏数据 。 终端2里,此时如果执行rollback回滚

终端1里,继续执行

select id,name from t_people where id=1;

可以发现最新结果,已经是回滚后的数据。很显然:如果有脏读问题出现,就更加保证不了“可重复读”。

2.2 不可重复读

将事务隔离级别设置成read committed(即:读已提交),可解决脏读问题,但满足不了“可重复读需求”。

验证方法跟刚才类似,终端1里输入:

set session transaction isolation level read committed;

将级别设置成RC,然后2个终端里都开启事务,终端2中,修改一行数据,但是不提交,此时终端1里应该是读不到终端2修改的数据。然后终端2提交,终端1才能读到修改后的数据。终端2如果继续修改、提交,终端1里再读取这1行,将是最新的值。(也就是只说,只要终端2不断修改,不断提交,终端1里就能读到这行不同的新值,即:保证不了同1个事务中,同一行数据,多次重复读取的值不变)

2.3 幻读

将隔离级别继续调整至Repeatable Read,还是刚才的场景,变成这样:

事务A对于同一行数据,不管读多少次,始终是相同的值,完全不理会有没有其它事务在修改它。有点:“两耳不闻窗外事,一心只读圣贤书”的味道。但是这也有问题,比如秒杀订单系统中,事务A第1次读取商品库存,发现还有1个,可以下单,赶紧继续,但是此时,可能有另一个事务,也在下单,已经提交了订单,把库存减为0了,事务A并不知道,因为多次读取库存的值是一样的,还是1,最后仍然把订单创建了,形成超卖。

验证方法:

set session transaction isolation level repeatable read;

剩下的步骤跟前面类似,就不重复赘述了。 

2.4 串行化

从db层面,要想同时解决脏读、不可重复读、幻读,只有串行化这个级别可以做到。

set session transaction isolation level serializable;

如下图:终端1设置串行化后,紧接着select xxx where id=1这条语句后,id=1的这行记录,就被锁了。

在终端2里,更新其它记录(即:id不等于1)可以正常成功,但是更新id=1 时,就会卡住,除非终端1把事务提交或回滚,否则将一直卡着,直到超时失败。

小结:

隔离级别   存在的问题
读未提交    脏读、不可重复读、幻读
读已提交   不可重复读、幻读
可重复读 幻读
串行化 性能问题

隔离级别越严格,db综合性能越低。

建议:

大多数情况下,RC(读已提交)基本上就足够了,如果并发度高,可以考虑“RC级别+(应用层)分布式锁”,这样即能保证数据正确,对db的性能压力也较低。

原文地址:https://www.cnblogs.com/yjmyzz/p/mysql-transaction-isolation-level.html

时间: 2024-10-12 21:36:41

mysql事务隔离级别/脏读/不可重复读/幻读详解的相关文章

MySQL事务隔离级别为"REPEATABLE-READ"下的"幻读"现象

MySQL事务隔离级别为"REPEATABLE-READ"下的"幻读"现象 关于mysql命令行中事务控制的语句见该文章:http://my.oschina.net/xinxingegeya/blog/296459 本片参考文章:http://blog.csdn.net/jiao_fuyou/article/details/16368827 http://www.cnblogs.com/hancf/archive/2012/08/28/2660422.html my

事务隔离级别中可重复读与幻读

前言 中秋刚过,大家是不是还没充中秋的假日里缓过来?三天假期里,我深入窥探了Innodb中可重复读与幻读,非常有意思,分享给大家,作为大家工作前的开胃小菜,希望有所帮助. 每次谈到数据库的事务隔离级别,大家一定会看到这张表. 其中,可重复读这个隔离级别,有效地防止了脏读和不可重复读,但仍然可能发生幻读,可能发生幻读就表示可重复读这个隔离级别防不住幻读吗? 我不管从数据库方面的教科书还是一些网络教程上,经常看到RR级别是可以重复读的,但是无法解决幻读,只有可串行化(Serializable)才能解

事务隔离级别中可重复读与幻读的恩恩怨怨

前言 中秋刚过,大家是不是还没充中秋的假日里缓过来?三天假期里,我深入窥探了Innodb中可重复读与幻读,非常有意思,分享给大家,作为大家工作前的开胃小菜,希望有所帮助. 每次谈到数据库的事务隔离级别,大家一定会看到这张表. 其中,可重复读这个隔离级别,有效地防止了脏读和不可重复读,但仍然可能发生幻读,可能发生幻读就表示可重复读这个隔离级别防不住幻读吗? 我不管从数据库方面的教科书还是一些网络教程上,经常看到RR级别是可以重复读的,但是无法解决幻读,只有可串行化(Serializable)才能解

数据库并发导致的脏读 不可重复读 幻读的处理方法

在做ERP订单接入仓库库存的时候出现了一个问题.下单会读取该商品是否有库存.如果有那么就下单 减去(可下单库存,物理库存不变) 没有则提示库存不足 在并发情况下就会导致 u1用户下单编号为1的商品1个  u2用户也下单编号为1的商品1个.编号为1的商品库存只有1个. 那么当u1在读取出数据的时候发现库存有一个 但是还没有写入库存的操作   u2也下单成功并提交  那么就会导致数据错乱 本来应该是只有u1会下单成功u2则提示库存不足 这里可以用事物的隔离机制或乐观锁来解决 事物是一个逻辑单元 原子

[MySQL]对于事务并发处理带来的问题,脏读、不可重复读、幻读的理解与数据库事务隔离级别 - 分析脏读 & 不可重复读 & 幻读

刚开始写博客.. 写的太low. 1.数据库的两种读,每种读读的数据版本不一样,所以也称为MVCC,即多版本并发控制 a) 快照读 select * from where xxx  这种形式的都是快照读. b) 当前读 update , insert ,delete ,select xx from xx for update ,  in share mode 都是当前读 当前读会等待,不会返回数据的历史版本 2.mvcc 的实现原理 mvcc是基于read view.活跃事务列表 做的,以后的文

理解数据库事务隔离级别以及脏读, 不可重复读, 幻读(转)

  转自:http://blog.csdn.net/sunxing007/article/details/6427290 数据库事务的4个特性: 原子性(atomic): 都成功或者都失败: 一致性(consistency):事务操作之后,数据库所处的状态和业务规则是一致的;比如a,b账户相互转账之后,总金额不变: 隔离性(isolation):操作中的事务不相互影响; 持久性(durability):事务提交后被持久化到数据库. 脏读,不可重复读, 幻读 幻读phantom read:事务1读

数据库事务隔离级别 - 分析脏读 & 不可重复读 & 幻读

一 数据库事务的隔离级别 数据库事务的隔离级别有4个,由低到高依次为Read uncommitted .Read committed .Repeatable read .Serializable ,这四个级别可以逐个解决脏读 .不可重复读 .幻读这几类问题. 1. Read UnCommitted(读未提交) 最低的隔离级别.一个事务可以读取另一个事务并未提交的更新结果. 2. Read Committed(读提交) 大部分数据库采用的默认隔离级别.一个事务的更新操作结果只有在该事务提交之后,另

商品分类-商品详情-数据库脏读-不可重复读-幻读-订单生成

商品详情的无限极分类 --北京 --朝阳区 ---上海 --松江 --大学城 def get_level(data): data_list=[] for item in data: if item['parent_id']==0: item['level']=0 else: item['level']=1 data_list.append(item) return data_list data=[ {"cat_id":1,"name":"北京",

脏读 不可重复读 幻读

脏读(Dirty Read)     脏读意味着一个事务读取了另一个事务未提交的数据,而这个数据是有可能回滚 不可重复读(Unrepeatable Read) 不可重复读意味着,在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据.这是由于查询时系统中其他事务修改的提交而引起的. 例如:事务B中对某个查询执行两次,当第一次执行完时,事务A对其数据进行了修改.事务B中再次查询时,数据发生了改变 幻读(phantom read) 幻读,是指当事务不是独立执行时发生的一种现象,例如第一个事务对