6.3.1 事务的基本概念

6.3.1 事务的基本概念

在介绍并发控制前,首先需要了解事务。数据库提供了增删改查等几种基础操作,用户可以灵活地组合这几种操作,实现复杂的语义。在很多场景下,用户希望一组操作可作为一个整体一起生效,这就是事务。事务就是用户定义的一个数据库操作序列,这些操作要么全做要么全不做,是一个不可分割的工作单位。所以说事务是数据库状态变更的基本单元,包含一个或多个操作(例如多条SQL语句)。

例如经典的转账事务,就包括3个操作:①检查A账户余额是否足够。②如果足够,从A扣减100元。③B账户增加100元。

1)事务的特征

事务具有4个基本特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)。这4个特性也被简称为事务的ACID特性。

(1)原子性

这一组操作要么一起生效,要么都不生效,事务执行过程中如遇错误,已经执行的操作要全部撤回,这就是事务的原子性。如果失败发生后,部分生效的事务无法撤回,那数据库就进入了不一致状态,就与真实世界的事实相左。例如转账事务:从A账户扣款100元后,转给B账户的时候失败了,B账户还未增加款项,如果A账户扣款操作未撤回,这个世界就莫名其妙丢失了100元。原子性可以通过记日志(更改前的值)来实现,还有一些数据库将事务操作缓存在本地,如遇失败,直接丢弃缓存里的操作。

(2)一致性

数据库反映的是真实世界,真实世界有很多限制,例如:账户之间无论怎么转账,总额不会变等现实约束;年龄不能为负值,性别只能是男、女选项等完整性约束。事务执行,不能打破这些约束,保证事务从一个正确的状态转移到另一个正确的状态,这就是一致性。一致性既依赖于数据库实现(原子性、持久性、隔离性也是为了保证一致性),也依赖于应用端编写的事务逻辑。

(3)隔离性

数据库为了提高资源利用率和事务执行效率、降低响应时间,允许事务并发执行。但是多个事务同时操作同一对象,必然存在冲突,事务的中间状态可能暴露给其他事务,导致一些事务依据其他事务中间状态,把错误的值写到数据库里。需要提供一种机制,保证事务执行不受并发事务的影响,让用户感觉,当前仿佛只有自己发起的事务在执行,这就是隔离性。隔离性让用户可以专注于单个事务的逻辑,不用考虑并发执行的影响。数据库通过并发控制机制保证隔离性。由于隔离性对事务的执行顺序要求较高,很多数据库提供了不同选项,用户可以牺牲一部分隔离性,提升系统性能。这些不同的选项就是事务隔离级别。

(4)持久性

事务只要提交了,它的结果就不能改变了,即使遇到系统宕机,重启后数据库的状态与宕机前一致,这就是事务的持久性。数据只要存储在非易失存储介质上,如硬盘,宕机就不会导致数据丢失。因此数据库可以采用以下两种方法来保证持久性:

①事务完成前,所有的更改都保证存储到磁盘上了。

②提交完成前,事务的更改信息,以日志的形式存储在磁盘,重启过程根据日志恢复出数据库系统的内存状态。一般而言,数据库会选择这种方法。

事务是数据库进行并发控制和恢复的基本单位。保证事务ACID特性是事务处理的重要任务,事务ACID特性可能遭到破坏的因素有:

多个事务并发执行时,不同事务的操作交叉执行;

事务在运行的过程中被强制停止。

在第一种情况下,数据库管理系统必须保证多个事务的交叉运行不影响这些事务的原子性,这是数据库并发控制机制的责任;在第二种情况下,数据库管理系统必须保证被强制终止的事务对数据库和其他事务没有影响,这是数据库管理系统中的恢复机制的责任。

2)事务的类型

按事务的启动和执行方式,可以将事务分为以下3类:

(1)显式事务

显式事务也称为用户定义或用户指定的事务,即显式地定义启动和结束的事务。

显式事务从Transact-SQL(T-SQL)命令BEGIN TRANSACTION开始,到COMMIT TRANSACTION或ROLLBACK TRANSACTION命令结束。也就是说,显式事务需要显式地定义事务的启动和提交。显示事务一般包含事务启动、事务提交和事务回滚过程。

①启动事务:启动事务使用BEGIN TRANSACTION语句,执行该语句会将系统变量@@TRANCOUNT加1。其语法格式如下:

BEGIN TRAN[SACTION][事务名|@事务变量名[WITH MARK[desp]]]

其中,WITH MARK[desp]用于在日志中标记事务,desp为描述该标记的字符串。如果使用了WITH MARK,则必须指定事务名。

②提交事务:如果没有遇到错误,可使用COMMIT TRANSACTION语句成功地提交事务。该事务中的所有数据修改在数据库中都将永久有效,事务占用的资源将被释放。

COMMIT TRANSACTION语句的语法格式如下:

COMMIT[TRAN[SACTION][事务名|@事务变量名]]

其中,各个参数的含义与BEGIN TRANSACTION中的相同。

③回滚事务:如果事务中出现错误,或者用户决定取消事务,可回滚该事务。回滚事务是通过ROLLBACK语句来完成的。其语法格式如下:

ROLLBACK[TRAN[SACTION][事务名|@事务变量名|保存点名|@保存点变量名]]

ROLLBACK TRANSACTION清除自事务的起点至某个保存点所做的所有数据更改,同时释放事务占用的资源。

【例6.9】 给出以下程序的结果。

该程序启动一个事务向student表中插入一个记录,然后回滚该事务。正是由于回滚了事务,所以student表中没有真正插入该记录。

【例6.10】 给出以下程序的结果。

该程序启动一个事务向student表中插入一个记录,然后提交该事务。由于事务已经提交,所以student表中有该同学的记录。

(2)自动提交事务

自动提交事务是SQL Server的默认事务管理模式。每个T-SQL语句在完成时,都被提交或回滚。如果一个语句成功地完成,则提交该语句;如果遇到错误,则回滚该语句。

SQL Server使用BEGIN TRANSACTION语句启动显式事务,或隐性事务模式设置为打开之前,将以自动提交模式进行操作。

(3)隐性事务

当连接以隐性事务模式进行操作时,SQL Server将在提交或回滚当前事务后自动启动新事务。无须描述事务的开始,只需提交或回滚每个事务。

在将隐性事务模式设置为打开之后,当SQL Server执行某些T-SQL语句时,都会自动启动一个事务,而不需要使用BEGIN TRANSACTION语句。这些T-SQL语句包括:ALTER TABLE、INSERT、OPEN、CREATE、DELETE、REVOKE、DROP、SELECT、FETCH、TRUNCATE TABLE、GRANT、UPDATE等。

在发出COMMIT或ROLL BACK语句之前,该事务会一直保持有效。在第一个事务被提交或者回滚之后,下次再执行这些SQL语句时,SQL Server都将自动启动一个新事务,不断地生成一个隐式事务链,直到隐式事务模式关闭为止。通过下列命令可以设置隐式事务模式的打开或关闭。

SET IMPLICIT_TRANSACTIONS{ON|OFF}

当设置为ON时,将SQL Server连接设置为隐式事务模式;当为OFF时,则使SQL Server连接返回为默认的自动提交事务模式。