MySQL innodb引擎四大事务隔离级别

网络上总结事务隔离级别的文章五花八门,大体上都是理论性的结论,今天我们不BB,直接show code。看看到底怎么理解。

mysql 默认的隔离级别是:REPEATABLE-READ

一.REPEATABLE-READ

打开两个会话,分别开启一个事务:

以下所有跨会话的操作都按编号顺序执行。

我们在会话1中更新一条数据,然后在会话2中查询,结果显示并未查到更改后的结果,再在会话1中查询,发现数据更新了,

结果理所当然应该这样,因为我们会话1中的事务并未提交。接下来我们提交会话1的事务,再查询2个会话中的结果。

 

结果和我们想的貌似不太一样,之前想当然认为会话1事务提交了之后 会话2应该能看到更新记录的,但是却没有。

然后我们提交会话2的事务,再查询。

这时候我们能看到会话1的事务更新的数据了。

结论:

在会话2的事务没提交之前,即使会话1的更新事务提交了,会话2的当前事务中也查不到更新后的记录,只有在会话2的事务提交之后,才能查到其他事务更新的记录。这就是默认的事务隔离级别REPEATABLE-READ 可重复读。

怎么理解呢?

在事务1中修改了表中的数据,事务2中查询的结果一直是事务1修改之前表中的数据,不管事务1有没有提交,只要事务2没有提交之前,事务2查询的结果都是原始的数据,对于事务2而言,当前表中的数据是可重复读的(前后查询结果是不会变化的),直到事务2也提交才会查到改变的记录。这是因为事务2读取的是一份数据的快照,只有事务2提交后,才会更新这个快照。

所以说REPEATABLE-READ 解决了不可重复读的问题,但是会出现幻读。

如下操作:

2个会话中同时开启一个事务,在事务1中插入一条记录,由上述结论可知:在第8步事务1提交之前,事务2中都查不到新插入的数据的,(如第9步所示)。但是我们在事务2中全量更新时,发现影响的行数为3(箭头所示),再查询时,直接查出了全量更新后的3条数据。(12步所示)

同样的一个查询sql 前后2次查询(9,12两步)发现莫名的多处一条数据,好像出现了幻觉似得,这就叫“幻读”。

 

这里要注意的是,上面我们在事务2中更新的操作是全量更新的,没有指定条件,下面我们来试下指定条件范围的更新,看看结果如何呢?

可见,在事务2中更新的指定的记录行时(8步),确实只更新了一条记录的数据。查询时也看不到事务1新增的地4条记录(9步),即使事务1提交了(10步),事务2也查不到新增的id为4的记录(11步),只有事务2提交了(12步),才能查到事务1新增的id为4的记录(13步)。

啊,有点乱,理一下,第一次试验,当事务2全量更新时(覆盖了事务1提交的id为3的记录时),事务2未提交也能查到事务1提交的id为3的记录,不过已经被我们全量更新了:name字段 "c"-->"ccc"。

第二次试验,事务2只更新能查到的id为3的记录,然后再提交事务1插入的id为4的记录。事务2是无感知的(11步),直到事务2提交之后才能感知事务1插入的新的数据。

我们再试下 事务1先提交,事务2再更新某一条记录的场景:

结果和第二次试验一样。都是直到事务2提交了,才能看到事务1提交的数据(id为5的数据)。

可见,幻读现象的出现还是有一定的条件的。

总结:REPEATABLE-READ 解决了不可重复读的问题,但是会出现幻读。

 

二.SERIALIZABLE 串行化

更改隔离级别:2个会话都要修改。

然后我们分别开启2个事务,在事务1中插入一条数据(5步),

发现箭头处没有插入成功返回。这是因为我们事务2开启了,过一段时间会报错:

当我们先在事务1中插入,再在事务2中查询的时候:

发现插入、能成功,查询阻塞了。

过段时间事务2查询也同样报错了:

此时事务1自动提交了。

 

然后事务1立马提交:再看事务2:

立马查出结果了,只不过因为串行化阻塞,查询耗时久了些12.15s。

可见,SERIALIZABLE 串行化完全牺牲了事务的并行能力的。

三.READ-COMMITTED 读已提交

同样的,开启2个事务,事务1修改一条记录,事务2查询,发现没有数据变化。事务1提交,事务2发现数据变了,事务2在同一次事务中前后2次查询出现了不同的结果,这个现象叫“不可重复读”。

READ-COMMITTED 读已提交 同样会引起“幻读”现象。

和上面“不可重复读”场景类似,事务2在一次事务中前后查询出不一致的结果,第二次查询比第一次查询结果多除了一条记录。好像是“幻觉”。

其实“不可重复读” 和“幻读”有些类似,区别在于“不可重复读”侧重于2次查询出的数据有被修改了,“幻读”侧重于2次查询的结果中有多出或者少掉的数据。

四.READ_UNCOMMITTED 读未提交(读到其他事务未提交的数据)

我们还是分别开启2个事务,在事务1中修改数据但不提交,发现事务2中前后2次查询数据不一样了,读到了事务1还未提交的修改,这种现象称之为“脏读”。

 

五.总结:

  • 脏读:指一个事务读取到了另外一个事务中未提交的数据。重点是别的事务还未提交...
  • 不可重复读(虚读):指一个事务中前后两次查询读取到了另外一个事务中提交的update的数据。
  • 幻读:指一个事务中的事务读取到了另外一个事务中提交的insert的数据。

 

隔离级别脏读(Dirty Read)不可重复读(NonRepeatable Read)幻读(Phantom Read)
未提交读(Read uncommitted)可能可能可能
已提交读(Read committed)不可能可能可能
可重复读(Repeatable read)不可能不可能可能
可串行化(Serializable )不可能不可能不可能
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值