深入理解mysql事务隔离级别

Posted imfx

tags:

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

mysql支持4种事务隔离级别分别为

Read Uncommitted 读未提交

Read Committed 读已提交

Repeatable Read 可重复读 *注意这个概念容易混,下面细说

Serializable 串行化事务操作

1.Read Uncommitted 读未提交

事务隔离级别设为Read Uncommitted时,能查询到其他事务已修改但尚未提交的数据,若后续其他事务发生回滚,则造成了脏读。是最低的事务隔离级别

2.Read Committed 读已提交

事务隔离级别设为Read Committed时,就不会查询到其他事务已修改但尚未提交的数据了,读取的都是其他事务已提交过的数据,避免了脏读。

但是会出现一种新的问题 不可重复读问题 如下

在Read Committed 级别下开启一个事务,先执行

select * from books where name = “计算机原理”

查询到图书信息 包括图书的数量,采购价格等,但此时另外一个事务修改了该图书的数量,并且进行了提交,那么接下来第一个事务

再使用  select * from books where name = “计算机原理” 查询时会发现图书的数量发生了变化,出现了前后查询不一致的问题,即不可重复读问题

 3.Repeatable Read 可重复读

事务隔离级别设为Repeatable Read可以避免不可重复读问题 但要注意 并不是禁止其他事务去修改,或者阻塞其他事务的更改,而是在该隔离级别下,同样的条件多次查询 使用的是一个快照,即第一次查询的结果,其他事务仍然可以对数据进行更改并提交。尽管使用的是快照结果但仍然可以保证事务的一致性,可通过如下方式进行验证 

例如 

事务A隔离级别设为Repeatable Read

开启事务A 查询 计算机原理图书的数量

 select total  from books where name = “计算机原理”

total 值为20,

然后其他事务修改计算机原理图书数量为29并进行了提交,

事务A再次执行

 select total  from books where name = “计算机原理”

total 值仍未20(上面有解释,这是一个快照)

事务A执行 更新操作 

update books set total = total - 1 where name = "计算机原理"

再次查询 select total  from books where name = “计算机原理” 会发现total为28 保证了事务的一致性。

在Repeatable Read隔离级别下,仍然有新的问题,即幻读

幻读是指,在一个事务中,第一次查询某条记录,发现没有,但是,当试图更新这条不存在的记录时,竟然能成功,并且,再次读取同一条记录,它就神奇地出现了。

4.Serializable 串行化事务操作

事务的最高隔离级别  可避免脏读,不可重复读,幻读

在该隔离级别下,开启事务 执行查询语句,在该查询范围内的数据如有其它事务进行更改或新增删除等,会被阻塞,强制依顺序执行事务,

例如

事务A隔离级别设为Serializable 

开启事务 执行 select *from books where name = “计算机原理” 

其它事务只要新增,更改,删除 name为“计算机原理”的行都会被阻塞强制按事务先后顺序执行,即事务A结束后,他们才能继续执行。

若事务A开启事务 执行 select *from books 则其它事务对这张表执行的增删改都会被阻塞,被迫按事务顺序执行,即事务A结束后,他们才能继续执行。

以上示例 都已在mysql上进行了验证 另外mysql事务默认隔离级别为Repeatable Read

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

MySQL深入理解MySQL锁和事务隔离级别

MySQL深入理解MySQL锁和事务隔离级别

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

深入理解mysql锁与事务隔离级别

事务隔离机制原理深入分析以及MySQL不同隔离级别分场景下实验对比

Mysql事务并发问题与隔离级别深入解析