事务ACID特性与隔离级别

栏目: 数据库 · 发布时间: 4年前

内容简介:事务指的是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。从业务角度出发,对数据库的一组操作要求保持4个特征:一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作。

事务指的是满足 ACID 特性的一组操作,可以通过 Commit 提交一个事务,也可以使用 Rollback 进行回滚。

ACID

从业务角度出发,对数据库的一组操作要求保持4个特征:

Atomicity(原子性):

一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作。

Consistency(一致性):

数据库在事务执行前后都保持一致性状态。在一致性状态下,所有事务对一个数据的读取结果都是相同的。

数据库总是从一个一致性状态转换到另一个一致状态。

Isolation(隔离性):

通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。注意这里的“通常来说”,后面的事务隔离级级别会说到。

Durability(持久性):

一旦事务提交,则其所做的修改就会永久保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。使用重做日志来保证持久性。(持久性的安全性与刷新日志级别也存在一定关系,不同的级别对应不同的数据安全级别。)

事务的 ACID 特性概念简单,但不是很好理解,主要是因为这几个特性不是一种平级关系:

  • 只有满足一致性,事务的执行结果才是正确的。
  • 在无并发的情况下,事务串行执行,隔离性一定能够满足。此时只要能满足原子性,就一定能满足一致性。
  • 在并发的情况下,多个事务并行执行,事务不仅要满足原子性,还需要满足隔离性,才能满足一致性。
  • 事务满足持久化是为了能应对数据库崩溃的情况。
事务ACID特性与隔离级别

AUTOCOMMIT

MySQL 默认采用自动提交模式。也就是说,如果不显式使用START TRANSACTION语句来开始一个事务,那么每个查询都会被当做一个事务自动提交。

并发一致性问题

在并发环境下,事务的隔离性很难保证,因此会出现很多并发一致性问题。

1. 更新丢失(Lost Update):

定义: 当两个或多个事务选择同一行,然后基于最初选定的值更新该行时,由于每个事务都不知道其他事务的存在,就会发生丢失更新问题,最后的更新覆盖了由其他事务所做的更新。

例如:

两个编辑人员制作了同一文档的电子副本。每个编辑人员独立地更改其副本,然后保存更改后的副本,这样就覆盖了原始文档。 最后保存其更改副本的编辑人员覆盖另一个编辑人员所做的更改。如果在一个编辑人员完成并提交事务之前,另一个编辑人员不能访问同一文件,则可避免此问题。

T1 和 T2 两个事务都对一个数据进行修改,T1 先修改,T2 随后修改,T2 的修改覆盖了 T1 的修改。

事务ACID特性与隔离级别

2. 脏读(Dirty Reads):

定义: 一个事务正在对一条记录做修改,在这个事务完成并提交前, 这条记录的数据就处于不一致状态; 这时, 另一个事务也来读取同一条记录,如果不加控制,第二个事务读取了这些“脏”数据,并据此做进一步的处理,就会产生未提交的数据依赖关系。这种现象被形象地叫做"脏读"。

T1 修改一个数据,T2 随后读取这个数据。如果 T1 撤销了这次修改,那么 T2 读取的数据是脏数据。

事务ACID特性与隔离级别

3. 不可重复读(Non-Repeatable Reads):

定义: 一个事务在读取某些数据后的某个时间,再次读取以前读过的数据,却发现其读出的数据已经发生了改变、或某些记录已经被删除了!这种现象就叫做“不可重复读” 。

T2 读取一个数据,T1 对该数据做了修改。如果 T2 再次读取这个数据,此时读取的结果和第一次读取的结果不同。

事务ACID特性与隔离级别

4. 幻读(Phantom Reads):

定义: 一个事务按相同的查询条件重新读取以前检索过的数据,却发现其他事务插入了满足其查询条件的新数据,这种现象就称为“幻读” 。

T1 读取某个范围的数据,T2 在这个范围内插入新的数据,T1 再次读取这个范围的数据,此时读取的结果和第一次读取的结果不同。

事务ACID特性与隔离级别

幻读和不可重复读的区别:

不可重复读的重点是修改: 在同一事务中,同样的条件,第一次读的数据和第二次读的数据不一样。(因为中间有其他事务提交了修改)

幻读的重点在于新增或者删除: 在同一事务中,同样的条件,,第一次和第二次读出来的记录数不一样。(因为中间有其他事务提交了插入/删除)

不可重复读和脏读的区别:

脏读是读到未提交的数据,而不可重复读读到的却是已经提交的数据。

隔离级别

SQL标准定义了4类隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。低级别的隔离级别一般支持更高的并发处理,并拥有更低的系统开销。

第1级别:Read Uncommitted(未提交读)

所有事务都可以看到其他未提交事务的执行结果

本隔离级别很少用于实际应用,因为它的性能也不比其他级别好多少

该级别引发的问题是——脏读(Dirty Read):读取到了未提交的数据

第2级别:Read Committed(提交读)

这是大多数数据库系统的默认隔离级别(但不是 MySQL 默认的)

它满足了隔离的简单定义:

一个事务只能读取已经提交的事务所做的修改。换句话说,一个事务所做的修改在提交之前对其它事务是不可见的。

这种隔离级别出现的问题是——不可重复读(Nonrepeatable Read):不可重复读意味着我们在同一个事务中执行完全相同的select语句时可能看到不一样的结果。导致这种情况的原因可能有:

有一个交叉的事务有新的commit,导致了数据的改变;

一个数据库被多个实例操作时,同一事务的其他实例在该实例处理期间可能会有新的commit

第3级别:Repeatable Read(可重复读)

这是MySQL的默认事务隔离级别

保证在同一个事务中多次读取同样数据的结果是一样的。

它确保同一事务的多个实例在并发读取数据时,会看到同样的数据行

此级别可能出现的问题——幻读(Phantom Read):当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行

InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决幻读问题;InnoDB还通过间隙锁解决幻读问题

MVCC 并不能解决幻读的问题,Next-Key Locks 就是为了解决这个问题而存在的。在可重复读(REPEATABLE READ)隔离级别下,使用 MVCC + Next-Key Locks 可以解决幻读问题。

第4级别:Serializable(可串行化)

这是最高的隔离级别,强制事务串行执行。

它通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。

在这个级别,可能导致大量的超时现象和锁竞争

事务ACID特性与隔离级别

小结

这篇文章给大家介绍了数据库事务定义的ACID特性和隔离级别,以及在不同的隔离级别下分别会产生哪些并发一致性问题,更新丢失、脏读、不可重复读、幻读都是我们要避免的,所幸MySQL的默认隔离级别为可重复读,其使用MVCC+next-key locks避免了幻读问题。其中的原理我将在下篇文章中给大家介绍。

参考自

zhuanlan.zhihu.com/p/29166694

github.com/CyC2018/CS-…


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Master Switch

The Master Switch

Tim Wu / Knopf / 2010-11-2 / USD 27.95

In this age of an open Internet, it is easy to forget that every American information industry, beginning with the telephone, has eventually been taken captive by some ruthless monopoly or cartel. Wit......一起来看看 《The Master Switch》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具