老生常谈关于MYSQL事务隔离级别(IsolationLevel)

一共有那几种隔离级别?分别叫什么?不同的隔离级别会有什么的问题?这些网上一搜一大把,我就不在墨迹了!看下面一个表就足够了。

隔离级别对照表
事务隔离级别 脏读 不可重复读 幻读
读未提交(read-uncommitted)
读已提交(read-committed)
可重复读(repeatable-read)
串行化(serializable)

有时候我自己也总是忘记“不可重复度”,“幻读”之间的区别。所以本文打算主要讲讲到底什么是不可重复读?什么是幻读?

不可重复读  

在一次事务中,每次查询到的数据不相同!

假设数据库中有名为person的表数据如下(共一行记录):

id name
1 zhangsan_v1

如下所示,打开俩个连接(打开俩个mysql终端或客户端)connection A 和 connection B 。蓝色虚线表示时间轴,connection A 开启一个事务,在执行期间 connection B 执行了一条insert 和 update 语句!

老生常谈关于MYSQL事务隔离级别(IsolationLevel)_第1张图片

第一次select 查询得到的结果如下:

老生常谈关于MYSQL事务隔离级别(IsolationLevel)_第2张图片

 

第二次select 查询得到的结果如下:

老生常谈关于MYSQL事务隔离级别(IsolationLevel)_第3张图片

可以看到 connection A 在一个事务中同一条查询语句得到不同的结果,产生了不可重复读的问题。

幻读

通俗点说:在同一事务中有些数据在读时候感受不到它们,但在写的时候却能感受到它们的存在!这些数据确是确实存在的,只是读不到而已。有点绕,看demo,就明白了!

假设数据库中有名为person的表数据如下(共俩行记录,id为主键):

id name
1

name1

2 name2

开启俩个mysql 连接 connection A 和 connectionB,设置 A 的事务为手动提交,隔离级别为重复读(repeatable read),在第8行第一次select 后 connecton B 执行了insert 占用主键:3,同时修改id = 1的name值从: name1 改为 name1_v2;

老生常谈关于MYSQL事务隔离级别(IsolationLevel)_第4张图片

 

第8行第一次select 结果如下:

老生常谈关于MYSQL事务隔离级别(IsolationLevel)_第5张图片

 

第12行第二次select 结果如下:

老生常谈关于MYSQL事务隔离级别(IsolationLevel)_第6张图片

可以看到在第二次select的时候,虽然connecton B 修改了表数据,但是connection A 还是查不到,和第一次select查询到的数据一致的,这就是可重复读。那么幻读是什么呢?注意,重点马上来了,看下面第14行insert 语句的执行结果;

 

第14行insert 语句执行结果:可以看到居然主键冲突了,可明明第二次select的时候没有查到id=3的数据啊,为啥insert的时候报主键冲突呢?其实这就是幻读。你读不到它,但它确实存在!

 

第20行代码执行结果如下:在18行结束事务后,可以看到id=1的name值为:name1_v2,并不等于name1_v3!第二次select 明明读到有name=name1的数据啊,可为啥第16行的update语句没有修改成功呢?因为幻读。你读到的name1,但底层的数据早已变成name1_v2了。

老生常谈关于MYSQL事务隔离级别(IsolationLevel)_第7张图片

你可能感兴趣的:(MySQL)