1.3 事务
在理解事务的概念之前,接触数据库系统的其他高级特性还言之过早。事务就是一组原子性的SQL查询
,或者说一个独立的工作单元。如果数据库引擎能够成功地对数据库应用该组查询的全部语句,那么就执行该组查询。如果其中有任何一条语句因为崩溃或其他原因无法执行,那么所有的语句都不会执行。也就是说,事务内的语句,要么全部执行成功,要么全部执行失败。
本节的内容并非专属于MySQL,如果读者已经熟悉了事务的ACID的概念,可以直接跳转到1.3.4节。
银行应用是解释事务必要性的一个经典例子。假设一个银行的数据库有两张表:支票(checking )表和储蓄(savings )表。现在要从用户Jane的支票账户转移200美元到她的储蓄账户,那么需要至少三个步骤:
-
检查支票账户的余额高于200美元。
-
从支票账户余额中减去200美元。
-
在储蓄账户余额中增加200美元。
上述三个步骤的操作必须打包在一个事务中,任何一个步骤失败,则必须回滚所有的步骤。
可以用START TRANSACTION 语句开始一个事务,然后要么使用COMMIT 提交事务将修改的数据持久保留,要么使用ROLLBACK 撤销所有的修改。事务SQL的样本如下:
1 START TRANSACTION;
2 SELECT balance FROM checking WHERE customer_id = 10233276;
3 UPDATE checking SET balance = balance - 200.00 WHERE customer_id = 10233276;
4 UPDATE savings SET balance = balance + 200.00 WHERE customer_id = 10233276;
5 COMMIT;
单纯的事务概念并不是故事的全部。试想一下,如果执行到第四条语句时服务器崩溃了,会发生什么?天知道,用户可能会损失200美元。再假如,在执行到第三条语句和第四条语句之间时,另外一个进程要删除支票账户的所有余额,那么结果可能就是银行在不知道这个逻辑的情况下白白给了Jane 200美元。除非系统通过严格的ACID测试,否则空谈事务的概念是不够的。
ACID表示原子性(atomicity)
、一致性(consistency)
、隔离性(isolation)
和持久性(durability)
。一个运行良好的事务处理系统,必须具备这些标准特征。
原子性(atomicity)
一个事务必须被视为一个不可分割的最小工作单元,整个事务中的所有操作要么全部提交成功,要么全部失败回滚,对于一个事务来说,不可能只执行其中的一部分操作,这就是事务的原子性。
一致性(consistency)
数据库总是从一个一致性的状态转换到另外一个一致性的状态。在前面的例子中,一致性确保了,即使在执行第三、四条语句之间时系统崩溃,支票账户中也不会损失200美元,因为事务最终没有提交,所以事务中所做的修改也不会保存到数据库中。
隔离性(isolation)
通常来说,一个事务所做的修改
在最终提交以前
,对其他事务是不可见
的。在前面的例子中,当执行完第三条语句、第四条语句还未开始时,此时有另外一个账户汇总程序开始运行,则其看到的支票账户的余额并没有被减去200美元。后面我们讨论隔离级别(Isolation level)的时候,会发现为什么我们要说“通常来说”是不可见的。
持久性(durability)
一旦事务提交,则其所做的修改就会永久保存到数据库中。此时即使系统崩溃,修改的数据也不会丢失。持久性是个有点模糊的概念,因为实际上持久性也分很多不同的级别。有些持久性策略能够提供非常强的安全保障,而有些则未必。而且不可能有能做到100%的持久性保证的策略(如果数据库本身就能做到真正的持久性,那么备份又怎么能增加持久性呢?)。在后面的一些章节中,我们会继续讨论MySQL中持久性的真正含义。
事务的ACID特性可以确保银行不会弄丢你的钱。而在应用逻辑中,要实现这一点非常难,甚至可以说是不可能完成的任务。一个兼容 ACID的数据库系统,需要做很多复杂但可能用户并没有觉察到的工作,才能确保ACID的实现。就像锁粒度的升级会增加系统开销一样,这种事务处理过程中额外的安全性,也会需要数据库系统做更多的额外工作。一个实现了ACID的数据库,相比没有实现ACID的数据库,通常会需要更强的CPU处理能力、更大的内存和更多的磁盘空间。正如本章不断重复的,这也正是MySQL的存储引擎架构可以发挥优势的地方。用户可以根据业务是否需要事务处理,来选择合适的存储引擎。对于一些不需要事务的查询类应用,选择一个非事务型的存储引擎,可以获得更高的性能。即使存储引擎不支持事务,也可以通过LOCK ABLES 语句为应用提供一定程度的保护,这些选择用户都可以自主决定。
1.3.1 隔离级别
下面介绍四种因为事务的并发产生的问题:
脏写
假设银行账户中有100元,
有事务A,B
A事务把余额改为200,但还未提交
这时,B事务把余额改为300,提交,
如果A发生了回滚,那么账户余额回到100元,事务B无效。
脏写就是已经提交的事务的写操作
因为另一个还未提交的事务的回滚而失去效果,请注意这个失效的事务应该是嵌在另一个事务的中间。
脏读
脏读与脏写十分类似,
脏读是因为另一个未完成的事务,发生了回滚,导致已提交的事务读出
的数据无效。
继续银行账户的例子,
如果银行账务中有100元,
有事务AB,
事务A首先开启,修改了账户余额为200,这时,
事务B开启,读到账户余额为200,事务B结束。
然后事务A发生了回滚,200这个数字失效,也就是B读到的是一个无效的数字,我们称之为脏读。
(脏读,脏写都是因为可以看到未提交的数据)
不可重复读
继续之前银行账户的例子,
有事务AB,银行账户中有100元
事务A开启,读出100元,
事务B开启,将100元修改为200元,
这时A又一次读取余额,发现余额竟然是200元。
在一个事务之内,读到了不一致的值
,我们称之为不可重复读。
不可重复读是因为在一个事务两次读操作的中间
有另一个事务进行了写操作。
幻读
与不可重复读十分类似,
但是这次要换一个例子,假设有一个班级的成绩单,其中有10人及格,
开启事务A,读到10人及格,
这时开启事务B,又向成绩表中写入了10条及格的数据,
事务A再次查询及格记录,发现竟然有20人及格。
一个事务两次读取的数据量
不一致,我们称之为幻读。
好像出现了幻觉。
隔离性其实比想象的要复杂。在SQL标准中定义了四种隔离级别,每一种级别都规定了一个事务中所做的修改,哪些在事务内和事务间是可见的,哪些是不可见的。较低级别的隔离通常可以执行更高的并发,系统的开销也更低。每种存储引擎实现的隔离级别不尽相同。如果熟悉其他的数据库产品,可能会发现某些特性和你期望的会有些不一样(但本节不打算讨论更详细的内容)。读者可以根据所选择的存储引擎,查阅相关的手册。
下面简单地介绍一下四种隔离级别。
READ UNCOMMITTED(未提交读)
有回滚的风险
在READ UNCOMMITTED 级别,事务中的修改,即使没有提交,对其他事务也都是可见的。事务可以读取未提交的数据,这也被称为脏读(Dirty Read)
(万一这个未提交的数据后面发生了回滚
,那么这次读的数据就是无效的,即脏数据
)。这个级别会导致很多问题,从性能上来说,READ UNCOMMITTED 不会比其他的级别好太多,但却缺乏其他级别的很多好处,除非真的有非常必要的理由,在实际应用中一般很少使用。
READ COMMITTED(提交读)
没有考虑事务发生的先后顺序
大多数数据库系统的默认隔离级别都是READ COMMITTED (但MySQL不是)。READ COMMITTED 满足前面提到的隔离性的简单定义:一个事务开始时,只能“看见”已经提交的事务所做的修改。换句话说,一个事务从开始直到提交之前,所做的任何修改对其他事务都是不可见的。这个级别有时候也叫做不可重复读(nonrepeatable read)
,(可以看到已经提交的修改,意味着在一个事务的执行过程中,第一次读的数据和第二次读的数据之间可能有另一个事务对这个数据进行了修改并提交,第二次读到的数据就是已经被修改提交的数据)因为两次执行同样的查询,可能会得到不一样的结果。
REPEATABLE READ(可重复读)
REPEATABLE READ 解决了脏读的问题。该级别保证了在同一个事务中多次读取同样记录的结果是一致的。但是理论上,可重复读隔离级别还是无法解决另外一个幻读(Phantom Read)的问题。所谓幻读,指的是当某个事务在读取某个范围内的记录时,另外一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生幻行(Phantom Row)。InnoDB和XtraDB存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)解决了幻读的问题。本章稍后会做进一步的讨论。
可重复读
是MySQL的默认事务隔离级别。
SERIALIZABLE(可串行化)
SERIALIZABLE 是最高的隔离级别。它通过强制事务串行执行,避免了前面说的幻读的问题。简单来说,SERIALIZABLE 会在读取的每一行数据上都加锁,所以可能导致大量的超时和锁争用的问题。实际应用中也很少用到这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。
![](E:\面试资料\高性能Mysql\图片附件\sql 隔离级别.png)
标签:语句,200,事务,隔离,提交,Mysql,级别 From: https://www.cnblogs.com/DCFV/p/18285727