SQL基础理论篇(十一):事务隔离

简介

之前我们讲过事务的四大特性,即ACID,分别是原子性、一致性、隔离性和持久性。隔离性就是事务的基本特性之一,可以防止数据库在并发处理时出现数据不一致的情况。

如果我们严格限制每一个事务是串行运行,这就意味着事务之间是相互独立的,但实际生产环境中,这样做是明显不可能的,因为随着用户量的增多,必然会存在大规模并发访问的情况,串行并不可取。于是我们通过设置不同的隔离级别,来换取事务的并发处理能力。

事务并发时的常见异常

首先我们需要了解事务在并发时会出现的一些异常情况,不同的隔离级别会分别解决不同的异常。

事务在并发时容易出现三种异常情况:

  • 脏读,即Dirty Read
  • 不可重复读,即Nonrepeatable Read
  • 幻读,即Phantom Read

事务的隔离级别,主要就是为了解决并发处理时会出现的这三种异常情况。

本小节,我们先介绍一下什么是脏读、不可重复读,和幻读。

什么是脏读?

简单的说,就是事务B读取了事务A尚未提交的数据。其实也叫做"无效数据读出"

假设事务A执行了一行insert,插入了一条新数据,但是它还没有commit,此时事务B对这张数据表进行了访问,就会读出这条新数据,这就是脏读。

至于为什么叫脏读,很好理解。如果在事务B读取了数据表之后,事务A因为其他原因被rollback了,那这条数据会被撤销插入。那么对事务B来讲,它刚刚读取到的,就是表里最终不存在的数据,或者说是无效的数据,所以叫脏读。

解决方法就是把数据库的隔离级别调整到READ_COMMITTED(读提交)。这个之后会讲。

什么是不可重复读?

简单的说,就是在同一事务里,对同一条记录,先后两次读取的结果不一样。

假设事务A需要执行两次select name from heros where id = 1;

第一次执行后返回的结果是"赵云"。

然而在它执行第二次查询之前,事务B被启动,对id=1的记录做了修改,即执行了update heros set name='张翼德' where id=1;,并提交。

那么之后事务A启动第二次查询的时候,返回的结果就是"张飞"。

像这种情况里,同一事务,先后两次查询的结果就会不一样,这就是不可重复读。

如图:

在这里插入图片描述

解决方法是把数据库的隔离级别调整到REPEATABLE_READ。

什么是幻读?

简单的说,就是在同一事务里,相同的查询条件,先后两次查询出的结果集行数不一致

事务A根据条件查询得到了N条数据,此时事务B删除或者增加了M条符合事务A查询条件的数据,并提交,这样当事务A再次按照相同条件查询的时候,会发现返回了N+M条数据,这就是幻读。跟发生了幻觉一样。

幻读跟不可重复读的区别在于,不可重复读是因为对同一条数据的修改,而幻读是因为数据的新增或者删除,即返回的记录数不一样。

事务的常用隔离级别

脏读、不可重复读和幻读,都是SQL-92标准中定义的,同时,92标准中还定义了4种隔离级别来解决这几种异常。

按照解决异常的数量,可以排列出隔离级别的高低,由低到高依次是:

  • 读未提交,即READ_UNCOMMITTED
  • 读已提交,即READ_COMMITTED
  • 可重复读,即REPEATABLE_READ
  • 可串行化,即SERIALIZABLE

这些隔离级别能解决的异常情况如下:

在这里插入图片描述

可以看到,可串行化可以避免所有的异常情况,而读未提交则允许所有异常情况。

读未提交,就是允许读到其他事务未提交的数据,这种情况下没有任何锁的存在,所以无法避免任何异常情况。

读已提交,就是只能读到其他事务已经提交的内容,可以避免脏读的发生,这也是RDBMS中常见的默认隔离级别,如Oracle和SQL Server。如果想进一步避免不可重复读和幻读,那就需要再结合上加锁的SQL。

可重复读,保证一个事务在相同查询条件下两次查询得到的数据结果是一致的,可避免脏读和不可重复读,但无法避免幻读。MySQL默认的隔离级别就是可重复读。

可串行化,将所有事务放在一个队列中串行执行,无法处理并发,所以多数情况下是理想态。

隔离级别越低,意味着数据库的吞吐量可以越大,即并发程度越高,但同时也意味着出现异常问题的可能性会更大。在实际使用过程中,我们需要在并发的性能和正确性上进行权衡,来选择合适的方案。

而事务的隔离级别,在底层是通过锁来实现 + 保证的,每个隔离级别需要的锁,之后会再介绍。

参考文献

  1. 15丨初识事务隔离:隔离的级别有哪些,它们都解决了哪些异常问题?
  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值