失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > MySQL 学习笔记(9)— 事务控制语句 事务属性以及并发和隔离级别

MySQL 学习笔记(9)— 事务控制语句 事务属性以及并发和隔离级别

时间:2020-10-21 02:47:44

相关推荐

MySQL 学习笔记(9)— 事务控制语句 事务属性以及并发和隔离级别

1. 事务概念

事务处理(transaction processing)可以用来维护数据库的完整性,它保证成批的MySQL操作要么完全执行,要么完全不执行。

下面是关于事务处理需要知道的几个术语:

事务(transaction)指一组SQL语句;回退(rollback)指撤销指定SQL语句的过程;提交(commit)指将未存储的SQL语句结果写入数据库表;保留点(savepoint)指事务处理中设置的临时占位符(placeholder),

你可以对它发布回退(与回退整个事务处理不同)。

事务仅仅适应于INSERTUPDATEDELETE,对SELECTCREATEDROP不生效。

2. 事务控制语句

SQL定义了用于管理数据库事务的事务控制语句(Transaction Control Language)。MySQL实现了以下语句:

BEGIN或者START TRANSACTION,开始一个事务;COMMIT,提交事务;ROLLBACK,撤销事务;SAVEPOINT,事务保存点,用于撤销部分事务;SET autocommit = {0 | 1},设置事务是否自动提交。

实际上,由于MySQL默认启用了自动提交(autocommit),任何数据操作都会自动提交:

show variables like 'autocommit';Variable_name|Value|-------------|-----|autocommit |ON |INSERT INTO bank_card VALUES ('62220803', 'C', 2000);

接下来我们看一下ROLLBACK命令的作用:

BEGIN;INSERT INTO bank_card VALUES ('62220804', 'D', 1000);ROLLBACK;

其中,BEGIN开始一个新的事务;然后插入一条记录;最后使用ROLLBACK撤销该事务。因此,最终不会创建卡号为 “62220804” 的记录。

Oracle支持事务管理的COMMITROLLBACK以及SAVEPOINT语句。Oracle中不需要手动开始事务,一个事务的结束意味着另一个事务的开始。

SQL Server支持事务管理的BEGIN TRANSACTIONCOMMITROLLBACK以及SAVE TRANSACTION语句。

PostgreSQL支持事务管理的BEGINCOMMITROLLBACK以及SAVEPOINT语句。

3. 事务的 ACID 属性

SQL标准定义了数据库事务的四种特性:ACID

3.1 原子性

原子性(Atomic)是指一个事务包含的所有SQL语句要么全部成功,要么全部失败。

例如,某个事务需要更新 100 条记录;但是在更新到一半时系统出现故障,数据库必须保证能够回滚已经修改过的数据,就像没有执行过任何修改一样。

3.2 一致性

一致性(Consistency)意味着事务开始之前,数据库位于一致性的状态;事务完成之后,数据库仍然位于一致性的状态。

例如,银行转账事务中;如果一个账户扣款成功,但是另一个账户加钱失败,就会出现数据不一致(此时需要回滚已经执行的扣款操作)。另外,数据库还必须保证满足完整性约束,比如账户扣款之后不能出现余额为负数(在余额字段上添加检查约束)。

3.3 隔离性

隔离性(Isolation)与并发事务有关,一个事务的影响在提交之前对其他事务不可见,多个并发的事务之间相互隔离。

例如,账户 A 向账户 B 转账的过程中,账户 B 查询的余额应该是转账之前的数目;如果多人同时向账户 B 转账,结果也应该保持一致性,和依次进行转账的结果一样。SQL 标准定义了 4 种不同的事务隔离级别,我们将会在下文进行介绍。

3.3 持久性

持久性(Durability)表示已经提交的事务必须永久生效,即使发生断电、系统崩溃等故障,数据库都不会丢失数据。

数据库系统通常使用重做日志(REDO)或者预写式日志(WAL)实现事务的持久性。简单来说,它们都是在提交之前将数据的修改操作记录到日志文件中;当数据库出现崩溃时,可以利用这些日志重做之前的修改,从而避免数据的丢失。

对于我们开发者而言,重点需要注意的是隔离级别,而隔离级别又与并发访问有关。

4. 并发和隔离级别

数据库的并发意味着多个用户同时访问相同的数据,例如 A 和 C 同时给 B 转账。数据库的并发访问可能带来以下问题:

4.1 脏读(Dirty Read

当一个事务允许读取另一个事务修改但未提交的数据时,就可能发生脏读。

例如,B 的初始余额为 0;A 向 B 转账 1000 元但没有提交;此时 B 能够看到 A 转过来的 1000 元,并且成功取款 1000 元;然后 A 取消了转账;银行损失了 1000 元。很显然,银行不会允许这种事情发生。

4.2 不可重复读(Nonrepeatable Read

一个事务读取某一记录后,该数据被另一个事务修改提交,再次读取该记录时结果发生了改变。

例如,B 查询初始余额为 0;此时 A 向 B 转账 1000 元并且提交;B 再次查询发现余额变成了 1000 元,以为天上掉馅饼了。

4.3 幻读(Phantom Read

一个事务第一次读取数据后,另一个事务增加或者删除了某些数据,再次读取时结果的数量发生了变化。幻读和非重复读有点类似,都是由于其他事务修改数据导致的结果变化。

4.4 更新丢失(Lost Update

第一类:当两个事务更新相同的数据时,如果第一个事务被提交,然后第二个事务被撤销;那么第一个事务的更新也会被撤销。第二类:当两个事务同时读取某一记录,然后分别进行修改提交;就会造成先提交的事务的修改丢失。

5. 隔离级别

为了解决并发访问可能导致的各种问题,SQL标准定义了 4 种不同的事务隔离级别(从低到高):

读未提交隔离级别最低,一个事务可以看到其他事务未提交的修改。该级别可能产生各种并发异常;如果一个事务已经修改某个数据,则另一个事务不允许同时修改该数据,写操作一定是按照顺序执行。PostgreSQL消除了读未提交级别时的脏读。读已提交只能看到其他事务已经提交的数据,不会出现脏读。可重复读可能出现幻读。MySQL中的Innodb存储引擎和PostgreSQL在可重复读级别消除了幻读。序列化提供最高级别的事务隔离。它要求事务只能一个接着一个地执行,不支持并发访问。

事务的隔离级别越高,越能保证数据的一致性;但同时会对并发带来更大的影响。不同数据库默认使用的隔离级别如下:

OracleSQL Server以及PostgreSQL默认使用读已提交隔离级别;MySQL InnoDB存储引擎默认使用可重复读隔离级别。

一般情况下,大多数数据库的默认隔离级别为读已提交;此时,可以避免脏读,同时拥有不错的并发性能。尽管可能会导致不可重复度、幻读以及丢失更新,但是可以通过应用程序加锁进行处理。

如果觉得《MySQL 学习笔记(9)— 事务控制语句 事务属性以及并发和隔离级别》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。