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

漫谈Mysql之事务ACID特性及事务隔离级别

什么是事务?

事务就是一组原子性的 SQL 语句,如果该组中的 SQL 有一条执行失败,那么所有的语句都不会执行。事务内的语句要么全部执行成功,要么全部执行失败。

以经典的银行转账为例:

假设银行的数据库有两张表:支票(checking)表和存储(savings)表,现在要从用户 A 的支票账户转移 200 元至她的存储账户,那么需要进行以下步骤:

检查支票账户的余额高于 200从支票账户余额中减去 200在存储账户余额中增加 200

假如执行完步骤 2,服务器崩溃导致步骤 3 没有执行,用户将会损失 200。

假如执行完步骤 2,另外一个进程要清除支票账户余额,银行将会白送 200。

所以,以上三个步骤的操作必须打包在一个事务中,不然就可能造成数据不一致的情况。

ACID特性

事务具有四个特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability),简称为事务的ACID特性。

原子性

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

一致性

数据库总是从一个一致性状态转换到另一个一致性状态。事务的执行不能破坏数据库数据的完整性和一致性。

隔离性

通常来说,一个事务所做的修改在最终提交以前,对其它事务是不可见的。但是出于对性能的考虑,实际上数据库并不会完全隔离,而是通过选择不同的隔离级别在可见性与性能之间进行取舍。

持久性

一旦事务提交,则其所做的修改会永久地保存到数据库中。此时,即使系统崩溃,修改的数据也不会丢失。

事务隔离级别

SQL 标准定义了四种隔离级别,每一种隔离级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。

读未提交(Read Uncommitted)

隔离级别最低,存在脏读,脏读会导致很多问题,实际应用中很少使用。

脏读(Dirty Read):一个事务中做了修改操作,但事务尚未提交,其它事务可以查询到修改后的数据

例:

账户A,资金余额100,事务1执行转账,从账户B转账100至账户A,事务2使用账户A执行购买150元的货物

事务1:执行转账操作,账户A资金+100,执行成功,账户余额200,事务尚未提交。

事务2:执行购买操作,检查账户资金,账户余额为200,判断可以购买,执行扣款-150,账户余额50,提交事务

事务1:执行转账操作,账户B资金-100,提交事务。

脏读发生在步骤二,事务2读取数据时,可以读取事务1尚未提交的数据变更。如果所有步骤都执行成功,最终数据还是可以保持一致性的。但是,如果步骤三执行失败,则步骤一会回滚,这样账户A在余额不够的情况下也购买成功。

读已提交(Read Committed)

解决了脏读问题,是大多数关系型数据库的默认事务隔离级别,存在不可重复读问题。

不可重复读(Nonrepeatable Read):在同一个事务中,前后执行两次同样的查询,可能会得到不一样的结果

例:

账户A,资金余额100,事务1执行资金检查,事务2使用账户A执行购买50元的货物

事务1:执行读取操作,账户A资金100,事务尚未提交。

事务2:执行购买操作,账户A资金-50,操作成功,账户A资金余额被修改为50。

事务1:执行读取操作,账户A资金50。

在事务1中,两次查询同一个数据,可能会得到不一致的结果。

可重复读(Repeatable Read)

解决了脏读及不可重复读的问题,MySQL的默认事务隔离级别,理论上存在幻读的问题。

幻读(Phantom Read):某个事务读取某个范围内的记录时,另外一个事务在该范围内插入了新的记录,之前的事务再次读取该范围的记录时,会产生幻行。

InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multi Version Concurrency Control)解决了幻读问题。

例:

执行用户注册操作,用户名为唯一键

事务1:执行读取操作,检查库中是否有用户名为‘aaa’的用户,结果显示没有,事务尚未提交。

事务2:执行插入操作,插入用户名为‘aaa’的用户数据。

事务1:执行插入操作,插入用户名为‘aaa’的用户数据,提示唯一键错误。

对于事务1而言,校验通过的情况下,执行插入却提示唯一键错误,如坠梦幻之中。

串行化(Serializable)

最高的事务隔离级别,在读取的每一行数据上都加锁,可能导致大量的超时和锁竞争问题,实际应用中很少使用。除非在必须确保数据一致性,并且可以接受没有并发的情况下,才考虑使用。

结束语

只有串行化隔离级别才能完全保障事务ACID特性,之所以出现隔离级别都是基于性能考虑,因串行化的并发处理能力不能满足实际生产需求。

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

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券