MySQL数据库事务的四种隔离级别

 

一.事务隔离级别:

事务具有ACID属性,而事务的隔离级别可以不同程度的解决事务并发时可能产生的问题,可以根据不同业务逻辑需求,来选择不同的事务隔离等级,事务隔离等级越高,越能保证数据的一致性,但就更趋近于串行化,降低并发性能,导致效率变低。

四种事务隔离级别:

读未提交(RU)    在这种隔离级别下,脏读、幻读、不可重复读都不能解决

读已提交(RC)    在这种隔离级别下,解决了脏读。

可重复读(RR)    在这种隔离级别下,解决了脏读、不可重复读。

序列化/串行化(Serializable)    在这种隔离级别下,解决了脏读、幻读、不可重复读。

从上往下,隔离强度逐渐增强,性能逐渐变差。采用哪种隔离级别要根据系统需求权衡决定,其中,可重复读是 MySQL 的默认级别。这四种隔离级别可以在不同程度上解决事务在并发时产生的问题——脏读,不可重复读,幻读。

1.脏读:有AB两个事务,B事务对一条数据进行修改,但未提交;而A事务在这之后对同一条数据进行读操作,读到的若是未提交的修改后的数据,就说明产生了脏读现象。

2.不可重复读:有一个A事务和若干其他事务,A事务对一条数据(或多条符合同一查询条件的数据)进行多次的读操作;其他的事务对A事务所读的数据进行了修改(这里不包括插入新的数据),若是未提交,在RU级别可以读到修改的数据,若是已提交,在RC级别及以下可以读到修改的数据;那么这种情况就可能会导致A事务在多次读取数据的时候,发现读取的数据值不一致,这种现象被称为不可重复读。

3.幻读:幻读的概念在网上很难找到一个全面且完全正确的解释,这里的解释是我个人的理解,可幻读是针对数据插入(INSERT)操作来说的。假设事务A对某些行的内容作了更改,但是还未提交,此时事务B插入了与事务A更改前的记录相同的记录行,并且在事务A提交之前先提交了,而这时,在事务A中查询,会发现好像刚刚的更改对于某些数据未起作用,但其实是事务B刚插入进来的,让用户感觉很魔幻,感觉出现了幻觉,这就叫幻读

MySQL事务隔离级别

事务隔离其实就是为了解决上面提到的脏读、不可重复读、幻读这几个问题,下面展示了 4 种隔离级别对这三个问题的解决程度。

事务隔离级别脏读不可重复读幻读
读未提交(read-uncommitted)
读已提交(read-committed)
可重复读(repeatable-read)
序列化/串行化(Serializable

只有串行化的隔离级别解决了全部这 3 个问题,其他的 3 个隔离级别都有缺陷。

1.未提交读(RU):

1.1实现机制:

事务在读数据的时候采用当前读

事务在修改数据的时候加共享锁,提交后释放(解决了修改时,数据被删除或修改的情况)

1.2脏读情况:会发生

创建一个表含以下信息并查看

再创建一个命令提示符对话框我们一共需要两个对话框解决问题接下来用A和B来解说两个框

左边是事务A框,右边是事务B框。

我们可以通过以下语句查看当前数据库的隔离级别AB都要有

show variables like 'transaction_isolation';
SELECT @@transaction_isolation

REPEATABLE-READ,也就是可重复读,这也是 MySQL 的默认级别AB都要有。 

 

稍后,我们要修改数据库的隔离级别(两个对话一样的操作)

  set session transaction isolation level read uncommitted;(修改隔离级别)

 修改后再次查询

 

开始事务A

BEGIN; -- 或者使用 START TRANSACTION;

 A事务查询表信息:

select * from runoob_shiwu2;

 

再次开启事务B
BEGIN; -- 或者使用 START TRANSACTION;
BEGIN;
打开B事务插入新数据,但不提交事务
INSERT INTO runoob_shiwu2 VALUES(1,1,2);

 打开A事务再次查询此表:读到了B事务未提交的操作,脏读情况发生,依旧读到了未提交的修改后的数据

select * from runoob_shiwu2;

1.3不可重复读情况:会发生

A事务查询id为30的数据

 select * from runoob_shiwu2 where id=30;

B事务对id为30的数据进行修改:提交与否不影响结果

update runoob_shiwu2 set num = 100 where id=30;

 A事务再次查询id为30的数据,与第一次读的num数据值不同,A事务在多次读取数据的时候,发现读取的数据值不一致,不可重复读情况发生

select * from runoob_shiwu2 where id=30;(查询)

1.4幻读情况:会发生

 A事务查询id<30的数据,

select * from runoob_shiwu2 where id<30;

 B事务插入一条id<30的数据,提交与否不影响结果

INSERT INTO runoob_shiwu2 values(10,10,3);

再次查询 A事务再次查询id<30的数据:查到的数据比第一次多一条,幻读情况发生

select * from runoob_shiwu2 where id<30;

2.已提交读(RC):

2.1实现机制:

事务在读数据的时候加读锁(当前读),读完即释放共享锁

事务在修改某数据时会加上写锁,直到事务结束再释放,这样的机制保证了RC隔离级别不会发生脏读,只有提交过的事务,才能被其他事务看见

2.2脏读情况:不会发生

和上面一样打开两个事务窗口AB,然后把事务隔离级别设置为RC,A,B一样

mysql> set session transaction isolation level read committed;

 开始事务并查询表的信息A,B一样

 

B事务插入新数据,但不提交:

A再次查询 没有读到B事务插入的数据,脏读情况没有发生

 

2.3不可重复读情况:会发生  

RC隔离级别下的不可重复读的情况和RU是类似的,只是B事务在修改数据的时候,需要提交。

COMMIT:事务确认,提交事务,使更改永久生效 

2.4幻读情况:会发生

RC隔离级别下的幻读的情况和RU是类似的,只是B事务在插入数据的时候,需要提交。

COMMIT:事务确认,提交事务,使更改永久生效

 3.可重复读(RR):

3.1脏读情况:不会发生

 首先是开启分别开启两个会话,后续会用A事务和B事务来代指这两个会话,然后把事务隔离级别设置为RR。

set session transaction isolation level repeatable read;

RR隔离级别下的脏读的情况和RC一样

3.2不可重复读情况:不会发生

开始事务begin; 

A事务查询id为30的数据:

B事务对id为30的数据进行修改:修改后提交事务

A事务再次查询id为30的数据:与第一次读的num数据值相同,没有发生不可重复读的情况

 3.3幻读情况:会发生

开始事务 

A事务查询表的全部数据

 B事务插入一条新数据:需要提交事务

A事务插入和B事务一样的数据

 

 A事务查询全部数据一开始可能会不显示多次查询就会出现幻读

 

4.序列化(Serializable):

实现机制:

事务在读取数据时,对整个表加读锁,提交或回滚事务后释放

事务在修改数据时,对整个表加写锁,提交或回滚事务后释放

这是最高的隔离级别,可以解决脏读,不可重复读和幻读,但同时效率也是最差的一个。它解决这些由于事务并发带了的问题的方法就是把这些操作变成串行操作,一旦不符合条件,就会被阻塞,所以效率特别差。

这个不用验证了,所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰了,一般不用,性能特别低。

参考

MySQL事务隔离级别_mysql 查看事务隔离级别-CSDN博客

MySql数据库——事务隔离级别和锁关系 - 付建国 - 博客园 (cnblogs.com)

  • 35
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值