Mysql事务的四大隔离级别及实现方式

Mysql的四大隔离界别及实现方式

Mysql的事务

本文主要讲解Mysql的四大隔离级别,因此,简略阐述Mysql的事务。Mysql的InnoDB引擎是支持事务的,之所以支持事务是因为Innodb通过提供redo log ,undo log等日志和锁机制等实现了事务的原子性,一致性,隔离性,持久性,具体实现原理可参见Mysql事务的ACID及其实现
针对事务的隔离性,sql标准将分为不同的隔离级别。

四大隔离级别

Mysql的四大隔离级分别为

  1. 读未提交(Read Uncommited):该隔离级别下事务可以读到其他事务还没有提交的数据
  2. 读(已)提交(Read Commited):该隔离级别下事务只能读到其他事务已经提交的数据
  3. 可重复读(Repeatable Read):该隔离级别主要解决了不可重复读问题,具体见后面详细分析。
  4. 串行化(Serializable):所有事务以串行的方式运行,并发度极低。

关于隔离级别中的三大问题

1. 脏读脏读的意思是事务在执行过程中会读到其他事务还没有提交的数据。
发生脏读的情况描述

很明显,事务可以读到其他事务还没有提交的数据,那么如果其他事务回退了,就会产生严重的不一致问题。

如果在某个事务1的执行过程中,另一事务2在数据库中插入一些数据,插入完后,事务1刚好执行了查询操作,查到了事务2插入的数据,可惜事务2因为某些原因执行出错而回退,那么事务1就相当于读到了一些没有的数据。

如何解决脏读问题

读已提交隔离级别解决了脏读问题。读已提交隔离级别下,事务仅能读到其他事务已经提交了的数据,这当然不会有脏读问题。

2. 不可重复读

不可重复度的意思是:在同一个事务中的两次查询中,后一次的查询会出现前一次查询的结果,这个不一样体现在后一次查到的数据可能已经被其他事务修改或者删除(注意:添加不算!!!,为什么,见后文)。因为两次查询得不到一样的结果,所以这个问题叫做不可重复读问题,因为重复读会出现不一样的结果嘛,这不是我们想要的结果。

不可重复读的举例

在这里插入图片描述

图中描述了不可重复读的一种情况,事务A的两次查询得到了不同的结果,是因为在两次查询之间,事务B删除了数据2,因此这两此查询结果不一样。所以说不可以在一次事务里重复读(查询),谓之不可重复读。

如何解决不可重复读问题

在查询的时候把范围内的所有数据加锁就行了,加锁以后,锁在整个事务提交以后才会释放,在这期间别的事务无法删除这个范围内的数据或修改这些数据。

3.幻读

幻读的意思是:在同一个事务中的两次查询中,后一次的查询相对于前一次会发现有新数据。(区别于不可重复读,不可重复读是说后一次查询发现比前一次查询少了数据或数据被修改了)。

为什么不可重复读不包括添加新数据的情况?

那是因为,一般解决不可重复读的都是采取加锁的方法解决的。在事务A查询时,把A查询的那些行(innodb支持行锁)都加上锁,那么在事务B中就无法删除或修改这些行了。但是,你却无法给一个不存在的行加上锁,数据都不在,你怎么加锁呢?这个时候,事务B还是可以在A的查询范围里加入新的行,所以将这个问题独立出来称为幻读。

幻读问题举例

在这里插入图片描述
上图所示,事务A两轮查询之间,虽然事务A在大于1小于10的行都加了锁,但是事务B还是可以插入新的数据,因此事务A在第二次查询中查到了不一样的结果。

幻读的解决方法:innodb中的间隙锁

sql标准中,可重复读隔离级别是没有解决幻读的。但是innodb引擎的可重复读隔离级别解决了幻读。innodb是使用间隙锁来解决幻读的,简单的说,在事务A查询的时候,把事务A查询的范围内的所有数据之间的间隙也加上锁,那么事务B就不能插入新数据了。拿上面的图的例子来说,事务A在查询(1,10)的数据的时候,1-2, 2-3, 3-10之间的间隙也加上锁,当然2,3本身也是会加锁的,而事务的锁是在提交之后才会释放的,这个时候事务B想要在3-10的间隙中加入一个5,就必须等待间隙锁的释放才能成功插入,所以此时,无论A查多少次都只能查到一样的结果。

回到四大隔离级别

1. 读未提交

读未提交是隔离性最低的隔离级别,事务之间会相互影响,这个隔离级别下会产生

  • 脏读(读到其他事务没有提交的数据),
  • 不可重复读(在两次相同查询之间,其他事务修改或删除了范围内的数据),
  • 幻读(在两次相同查询之间,其他事务在范围内添加了新数据)
2. 读已提交

读已提交解决了脏读问题,很显然,事务只能读到其他已提交事务的数据,因此脏读的问题得到了解决。但是仍然存在

  • 不可重复读(两次相同查询之间,其他事务修改了或删除了范围内数据并且提交了,导致两次查询结果不一样),
  • 幻读(两次相同查询之间,其他事务在范围内添加新数据并且提交了,导致两次查询结果不一样)
3. 可重复读

可重复读隔离级别在sql标准中只解决了可重复读问题,但是innodb引擎的该级别同时也解决了幻读问题。InnoDB通过锁机制,在查询的时候,锁住查询范围内的所有数据,而且这个锁在事务提交以后才会释放,这样同一事务下的两次相同查询之间,其他事务无法修改或删除查询范围内的数据,这就解决了不可重复读问题。InnoDB使用间隙锁锁住行与行之间的间隙,这样其他事务就不能在查询范围内添加新数据,解决了幻读问题。

InnoDB的MVCC(多版本并发控制)

由于这个级别下,使用了锁机制,锁机制的一大缺点就是锁竞争会影响并发度。MVCC实现了非锁定读,通俗的说在读的时候不需要加锁就能读到事务开始哪个时刻对应的版本的数据。MVCC通过在数据中加入隐藏的版本号相关的数据列,然后结合innodb的undo log,在非锁定性读的时候,可以根据版本号,利用undo log将当前数据回退到对应版本数据。MVCC的目的就是在读数据的时候可以不适用锁,提高并发度。这里只做大致阐述,细节请自行搜索相关知识。

4. 串行化

所有事务串行执行,并发度极低,显然不会有任何的脏读,不可重复读,幻读的问题产生。但是串行执行并发度极低,因此基本不使用这个隔离级别。

附四大隔离级别对应会产生的问题

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值