首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

事务系列之一 概念

之前下定决心要坚持写博客的习惯,最终不了了之,现在再次重新下定决心,从此篇博客开始吧。

开发的同学应该都听过事务这个概念,但是在实际工作过程中还是会有同学,因为对事务理解过于表面,会出现这样或那样的故障。

下来来看看MySQL官网怎么定义事务

Transactions are atomic units of work that can becommittedorrolled back. When a transaction makes multiple changes to the database, either all the changes succeed when the transaction is committed, or all the changes are undone when the transaction is rolled back.

Database transactions, as implemented by , have properties that are collectively known by the acronymACID, for atomicity, consistency, isolation, and durability.

内容引用链接:

https://dev.mysql.com/doc/refman/5.7/en/glossary.html#glos_transaction

大致就是说:原子的工作单元集可以被提交或者回滚,当事务对数据库做了多个改变时,要么全部提交成功,要么全部回滚不做,并有4个特性ACID.

ACID是Jim Gray在1983收集整理出来的概念,对后面的数据库系统的设计开发有较大的影响,实际上早在1973年IBM Information Management System已经支持这四种特性了,尽管ACID的概念晚出来10年。

4个事务特性如下:

原子性(atomicity)

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

一致性(consistency)

数据库总是从一个一致性的状态转换到另一个一致性的状态。(在前面的例子中,一致性确保了,即使在执行第三、四条语句之间时系统崩溃,支票账户中也不会损失200美元,因为事务最终没有提交,所以事务中所做的修改也不会保存到数据库中。)

隔离性(isolation)

通常来说,一个事务所做的修改在最终提交以前,对其他事务是不可见的。(在前面的例子中,当执行完第三条语句、第四条语句还未开始时,此时有另外的一个账户汇总程序开始运行,则其看到支票帐户的余额并没有被减去200美元。)

持久性(durability)

一旦事务提交,则其所做的修改会永久保存到数据库。(此时即使系统崩溃,修改的数据也不会丢失。持久性是个有点模糊的概念,因为实际上持久性也分很多不同的级别。有些持久性策略能够提供非常强的安全保障,而有些则未必,而且不可能有能做到100%的持久性保证的策略。)

其中隔离性(isolation)在ISO/IEC 9075:1992, Database Language SQL标准中定义为四个级别和三个并发事务处理时会出现的现象。(SQL92标准原文:https://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt)

4个隔离级别如下:

READ UNCOMMITTED(未提交读)

在READ UNCOMMITTED级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为脏读(Dirty Read)。这个级别会导致很多问题,从性能上来说,READ UNCOMMITTED不会比其他的级别好太多,但却缺乏其他级别的很多好处,除非真的有非常必要的理由,在实际应用中一般很少使用。

READ COMMITTED(提交读)

大多数数据库系统的默认隔离级别都是READ COMMTTED(但MySQL不是)。READ COMMITTED满足前面提到的隔离性的简单定义:一个事务开始时,只能"看见"已经提交的事务所做的修改。换句话说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。这个级别有时候叫做不可重复读(nonrepeatble read),因为两次执行同样的查询,可能会得到不一样的结果

REPEATABLE READ(可重复读)

REPEATABLE READ解决了脏读的问题。该隔离级别保证了在同一个事务中多次读取同样记录结果是一致的。但是理论上,可重复读隔离级别还是无法解决另外一个幻读(Phantom Read)的问题。所谓幻读,指的是当某个事务在读取某个范围内的记录时,另一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题。

SERIALIZABLE(可串行化)

SERIALIZABLE是最高的隔离级别。它通过强制事务串行执行,避免了前面说的幻读的问题。简单来说,SERIALIZABLE会在读取每一行数据都加锁,所以可能导致大量的超时和锁争用问题。实际应用中也很少用到这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。

三个现象如下(事务T1、T2并发执行时):

脏读(dirty read) 一个事务读取了另一个事务尚未提交的数据

当T2事务update后,T1事务select读取到T2尚未提交的数据,此时T2事务rollback,则T1读到的数据是无效的"脏"数据。脏读会有什么后果呢?

举个栗子:

产品PRD文档说明只处理三天的数据,下午产品就说需求有变更,但是只是口头说明变更为处理一天的数据.

技术按照产品口头描述的处理一天数据,上线了。后来出现了问题。实际是要处理三天的数据,诬陷技术没按照文档来开发。

技术脏读了产品的口头需求,暗自伤悲…

不可重复读(non-repeatable read) 一个事务的操作导致另一个事务前后两次读取到不同的数据

当T1事务select读取数据后,T2事务update操作更改T1事务select到的数据,此时T1事务再次读去该数据,发现前后两次的数据不一样。不可重复读有什么后果呢?

举个栗子:

技术开发完成,提交测试。技术这时发现一个bug,修复又引起其它未知bug,并悄悄部署在测试环境

测试很苦恼,刚测试确认流程1、2 ok的,执行相同操作,单条数据值怎么变得不一样了?

幻读(phantom read) 一个事务的操作导致另一个事务前后两次查询的结果数据量不同。

当T1事务select读取数据后,T2事务insert或delete了一条满足T1事务的select条件的记录,此时T1事务再次select,发现查询到前次不存在的记录("幻影"),或者前次的某个记录不见了。幻读和不可重读的区别在于:幻读是数据量不同,而不可重复读是同样的一条数据,其中的值发生了变化。

隔离级别和并发事务现象的对应关系如下:

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20171231G0NAV900?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券