MySQL事务隔离级别(2022.05.15)

Posted Mr. Dreamer Z

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MySQL事务隔离级别(2022.05.15)相关的知识,希望对你有一定的参考价值。

事务是什么?

一般是指要做的或所做的事情

为什么要引入事务?

为了保证工作流程中操作的数据的可靠性

原子性(Atomicity):指的是事务是一个不可分割的单位,要么事务中的所有的操作全部成功,要么全部失败;——操作层面

一致性(Consistency):和原子性类似,只不过在数据层面。指的是事务必须在执行前后满足数据库的所有约束。(这个约束我认为是指:有一个操作,其中A,B,C三步都需要修改数据,那么这三步操作数据要么都成功,要么都失败。成功或者失败得到的数据结果就代表数据库的约束)

隔离性(isolation):不同事务之间的操作,互不影响

持久性(durability):数据一经提交永久保存

目录

1.隔离性

1.1 读未提交

1.2 读已提交

1.3 可重复读

1.4 可串行化


1.隔离性

隔离性分为四个隔离级别:读未提交、读已提交,可重复读、串行化。

事务的隔离级别

由上图我们可得知不同隔离级别带来的问题。

下面,让咱们来亲自动手试试,毕竟不断地重复才能加深我们的映像!话不多说,开始

查看当前事务隔离级别

select @@tx_isolation;

先创建一个表,丢几条数据进去

CREATE TABLE `account` ( 
`id` int(11) NOT NULL AUTO_INCREMENT, 
`name` varchar(255) DEFAULT NULL, 
`balance` int(11) DEFAULT NULL, 
PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `account` (`name`, `balance`) VALUES ('lilei', '450');
INSERT INTO `account` (`name`, `balance`) VALUES ('hanmei', '16000');
INSERT INTO `account` (`name`, `balance`) VALUES ('lucy', '2400');

1.1 读未提交

根据上图可知,读未提交这个隔离级别是最低级的隔离级别了。

它会造成:脏读、不可重复读、幻读。

咱们来看看脏读是怎么一回事:

脏读:事务A读取到了事务B修改但未提交的数据

先设置隔离级别为读未提交

set tx_isolation='read-uncommitted';

咱看看原始的数据先

客户端A开启事务

修改数据;但还未提交

客户端B开启事务之后查看,发现此时,读到了客户端A修改但是还未提交的数据。

 然后客户端A操作回滚

客户端B再去查询,发现依旧读取到了未提交的数据

以上现象就是脏读

1.2 读已提交

在该隔离级别中,会造成:不可重复读、幻读;

不可重复读:当前事务在单位时间内连续两次读取数据,发现两次读到的数据结果都不一致;

首先,先将隔离级别改为读已提交

set tx_isolation='read-committed';

然后,在客户端A开启事务改动数据,但是不提交

 在客户端B查询

此时我们发现,客户端B读取到的还是之前的数据,并未读到事务1修改但未提交的数据,避免了脏读现象。

接着,客户端A提交事务

在客户端B中进行查询,发现两次得到的结果不一样

这就是不可重复读

1.3 可重复读

在可重复读这一隔离级别,会产生幻读

幻读:简单来说,就是在当前事务进行读操作,第一次读,发现总共有3条数据。第二次读,就发现有不等于3条数据的数量。

咱们先将隔离级别改为可重复读(MySQL默认的隔离级别

set tx_isolation='repeatable-read';

先试试,能不能解决不可重复读呢?

在客户端A中开启事务修改数据,然后提交事务。

 然后在客户端B中进行查看

 发现不可重复读问题已经解决了。

咱们再来看看,幻读的问题

客户端A新增一条数据之后,提交事务

客户端B进行查询

 发现两次读到的数据条数不一样了,这就是幻读;

1.4 可串行化

这是最高等级的隔离级别,能够解决所有问题。

设置隔离级别

set tx_isolation='serializable';

客户端A上进行查询操作,针对id=1的数据

 然后在客户端B进行更新,也针对id=1的数据

 但是呢,发现id=1的数据已经被锁了。

咱们来试试id=2的数据,能否被修改吗。

 发现是没有问题。

那么先修改再查询呢?

 

还是不行。。。。

那是为什么会这样呢?先上结论

如果客户端A执行的是一个范围查询,那么该范围内的所有行包括每行记录所在的间隙区间范围(就算该行数据还未被插入也会加锁,这种是 间隙锁 )都会被加锁。此时如果客户端B在该范围内插入数据都会被阻塞,所以就避免了幻读。 感觉有点乱呢,让我们通过例子来理一理 这是咱们的数据

id为1,4,6.  那么对应的区间是[1,4],[4,6],[6,+∞)

客户端A修改id>1且id<7的数据

客户端B查询id=4的数据

 发现无法查询,其原因就是因为间隙锁将对应区间的数据给锁住了。别着急,接着往下看

再来试试,客户端A修改id>1且id<5的数据

事务2查询id=6的数据

发现还是锁住了,咋不对呢?我明明没有修改这个范围内的数据啊!

这就是所谓的间隙锁了

刚刚提到,咱们当前数据对应的区间是[1,4],[4,6],[6,+∞)。那我修改的是(1,5)的数据,为啥还是不能修改id=6的数据呢?

原因就是因为id=6的数据,在[4,6]这个区间。所以,id=6这条数据就被锁住了。

那么id=7的数据可以插入吗?

那么咱们继续试试嘛,插入一条id=7的数据。

插入成功之后,客户端A还是修改区间(1,5)的数据

客户端B我们来查询id=7的数据,以及查询id=4的数据

按照上图的结果,可以验证我们刚才所说的,间隙锁锁住的区间。所以id=7可以查询,id=4不能。

~stay hungry,stay foolish

以上是关于MySQL事务隔离级别(2022.05.15)的主要内容,如果未能解决你的问题,请参考以下文章

MySQL事务隔离级别(2022.05.15)

白话Mysql的锁和事务隔离级别!死锁间隙锁你都知道吗?

MYSQL性能调优08_事务及其ACID属性脏读不可重复读幻读隔离级别行锁表锁读锁写锁间隙锁临键锁

事务隔离级别

mysql 事物隔离级别rr还是rc好

深入理解Mysql事务隔离级别与锁机制