13.7 事务处理
对于任何数据库应用而言,事务都是非常重要的,事务是保证底层数据完整的重要手段,没有事务支持的数据库应用,那将非常脆弱
13.7.1 事务的概念和MySQL事务支持
事务是由一步或几步数据库操作序列组成的逻辑执行单元,这系列操作要么全部执行,要么全部放弃执行。
程序和事务是两个不同的概念。一般而言,一段程序中可能包含多个事务。
事务的4个特性
事务具备4个特性:
- 原子性(
Atomicity)
, - 一致性(
Consistency)
, - 隔离性(
Isolation)
, - 持续性(
Durability)
。
这4个特性也简称为ACID
性
原子性
原子性( Atomicity)
:事务是应用中最小的执行单位,事务是应用中不可再分的最小逻辑执行体。
一致性
一致性( Consistency)
:事务执行的结果,必须使数据库从一个一致性状态,变到另一个一致性状态。当数据库只包含事务成功提交的结果时,数据库处于一致性状态。如果系统运行发生中断,某个事务尚未完成而被迫中断,而该未完成的事务对数据库所做的修改已被写入数据库此时,数据库就处于一种不正确的状态。比如银行在两个账户之间转账:从A账户向B账户转入1000元,系统先减少A账户的1000元,然后再为B账户增加1000元。如果全部执行成功,数据库处于一致性状态;如果仅减少A账户金额,而没有增加B账户的金额,则数据库就处于不一致性状态;因此,一致性是通过原子性来保证的。
隔离性
隔离性( Isolation)
:各个事务的执行互不干扰,任意一个事务的内部操作对其他并发的事务都是隔离的。也就是说,并发执行的事务之间不能看到对方的中间状态,并发执行的事务之间不能互相影响。
持续性
持续性( Durability)
:持续性也称为持久性( Persistence)
,指事务一旦提交,对数据所做的任何改变都要记录到永久存储器中,通常就是保存进物理数据库。
事务语句组成
数据库的事务由下列语句组成。
- 一组
DML
语句,经过这组DML
语句修改后的数据将保持较好的一致性。(DML指的是:insert,update,delete这三条SQL语句)
- 一条
DDL
语句。(DDL
指的是create
,alter
,drop
,truncate
等语句) - 一条
DCL
语句。(DCL
指的是:grant
等语句)
注意
事务中的DDL
和DCL
语句最多只能有一条,因为DDL
和DCL
语句都会导致事务立即提交。
提交
当事务所包含的全部数据库操作都成功执行后,应该提交( commit)
事务,使这些修改永久生效。
事务提交有两种方式:显式提交
和自动提交
。
- 显式提交:使用
commit
时. - 自动提交:执行
DDL
或DCL
语句,或者程序正常退出时。
回滚
当事务所包含的任意一个数据库操作执行失败后,应该回滚(rollback)
事务,使该事务中所做的修改全部失效。事务回滚有两种方式:显式回滚
和自动回滚
。
- 显式回滚:使用
rollback
。 - 自动回滚:系统错误或者强行退出。
如何开启 关闭事务
MySQL
默认关闭事务(即打开自动提交),在默认情况下,用户在MySQL
控制台输入一条DML
语句,这条DML
语句将会立即保存到数据库里。为了开启MySQL
的事务支持,可以显式调用如下命令:
1 | SET AUTOCOMMIT={0|1} #0为关闭自动提交,即开启事务 |
注意:自动提交和开启事务恰好相反,如果开启自动提交就是关闭事务;关闭自动提交就是开启事务。
临时开启事务
除此之外,如果不想关闭整个命令行窗口的自动提交,而只是想临时性地开始事务,则可以使用MySQL
提供的start transaction
或begin
两个命令,它们都表示临时性地开始一次事务,处于starttransaction
或begin
后的DML
语句不会立即生效,除非使用commit
显式提交事务,或者执行DDL
、DCL
语者来隐式提交事务。如下SQL
代码将不会对数据库有任何影响。
1 | begin; |
执行上面SQL
语句中的第①条查询语句将会看到刚刚插入的3条记录,如果打开MySQL
的其他命令行窗口将看不到这3条记录—这正体现了事务的隔离性
。
接着程序rollback
了事务中的全部修改,执行第②条查询语句时将看到数据库又恢复到事务开始前的状态。
对于提交,不管是显式提交还是隐式提交,都会结束当前事务;
对于回滚,不管是显式回滚还是隐式回滚,都会结束当前事务。
保存点
除此之外, MySQL
还提供了savepoint
来设置事务的中间点,通过使用savepoint
设置事务的中间点可以让事务回滚到指定中间点,而不是回滚全部事务。如下SQL
语句设置了一个中间点:
1 | savepoint a; |
一旦设置了中间点后,就可以使用rollback
回滚到指定中间点,回滚到指定中间点的代码如下:
1 | rollback to a; |
注意:
普通的提交、回滚都会结束当前事务,
但回滚到指定中间点因为依然处于事务之中,所以不会结束当前事务.