20 管理事务处理
1.事务处理
通过事务处理,通过确保成批的SQL操作要么完全执行,要么完全不执行,来维护数据库的完整性。
事务处理是一种机制,用来管理必须成批执行的SQL操作,保证数据库不包含不完整的操作结果。利用事务处理,可以保证一组操作不会中途停止,它们要么完全执行,要么完全不执行。如果没有错误发生,整组语句提交给数据库表;如果发生错误,则进行回退,将数据库恢复到某个已知且安全的状态。
假设订单存储在Orders和OrderItems表中,Orders存储实际的订单,OrderItems存储订购的各项物品。这两个表使用称为主键的唯一ID互相关联,又与包含客户和产品信息的其他表相关联。
给系统添加订单的过程如下:
(1)检查数据可中是否存在相应的顾客,若不存在则添加该顾客;
(2)检索顾客的ID;
(3)在Orders表添加一行,它与顾客ID相关联;
(4)检索Order表中赋予的新订单ID;
(5)为订购的每个物品在OrderItems表中添加一行,通过检索出来的ID把它与Orders表以及Products表关联。
假设由于某种数据库故障,该过程无法完成。
若故障发生在添加顾客之后,添加Orders表之前,则不会有问题。可以有效地从出故障的地方开始执行此过程。
若故障发生在插入Orders行之后,添加OrderItems行之前。这样数据库有一个空订单。
而若系统在添加OrderItems行之时出现故障,这时数据库将存在未知的不完整的订单,这样更糟糕。此时需要使用事务处理。
该工作过程如下:
(1)检查数据可中是否存在相应的顾客,若不存在则添加该顾客;
(2)提交顾客信息;
(3)检索顾客的ID;
(4)在Orders表添加一行;
(5)若向Orders表添加行时出现故障,回退;
(6)检索Order表中赋予的新订单ID;
(7)对于订购的每项物品,添加新行到OrderItems表;
(8)若向OrderItems添加行时出现故障,回退所有添加的OrderItems行和Orders行。
几个术语:
-
事务:一组SQL语句;
-
回退:撤销指定SQL语句;
-
提交:将未存储的SQL语句结果写入数据库表;
-
保留点:事务处理中设置的临时占位符,可以对它发布回退。
可回退:INSERT、UPDATE、DELETE语句;
不可回退:SELECT(也没必要)、CREATE、DROP操作。
2.控制事务处理
管理事务的关键在于将SQL语句组分解为逻辑块,并明确规定数据何时应该回退,何时不应该回退。
有的DBMS要求明确标识事务处理块的开始或结束。
MySQL中的标识,输入:
START TRANSACTION
...
多数实现没有明确表示事务处理在何处结束,事务一直存在,直到被中断。通常,COMMIT用于保存更改,ROLLBACK用于撤销。
(1)使用ROLLBACK
SQL的ROLLBACK命令用来回退SQL语句。
输入:
DELETE FROM Orders;
ROLLBACK;
(2)使用COMMIT
使用COMMIT语句进行明确的提交。
一个SQL Server列子,输入:
BEGAIN TRANSACTION
DELETE OrderItems WHERE order_num = 12345
DELETE Orders WHERE order_num = 12345
COMMIT TRANSACTION
(3)使用保留点
要支持回退部分事务,必须在事务处理块中的合适位置放置占位符。SQL中,这些占位符称为保留点。
MySQL中,可以使用SAVEPOINT语句。
输入:
SAVEPOINT delete1;
每个保留点具有能够标识它的唯一名字,以便在回退时,DBMS知道回退到何处。MySQL中,要回退到该保留点,可以输入:
ROLLBACK TO delete1;
一个完整的SQLServer例子:
BEGIN TRANSACTION
INSERT INTO Customers(cust_id, cust_name)
VALUES('1000000010', 'Toys Emporium');
SAVE TRANSACTION StartOrder;
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20100,'2001/12/1','1000000010');
IF @@ERROR <> 0 ROLLBACK TRANSACTION StartOrder;
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20100, 1, 'BR01', 100, 5.49);
IF @@ERROR <> 0 ROLLBACK TRANSACTION StartOrder;
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20100, 2, 'BR03', 100, 10.99);
IF @@ERROR <> 0 ROLLBACK TRANSACTION StartOrder;
COMMIT TRANSACTION
该事务处理块中包含了4条INSERT语句。在第一条INSERT语句之后定义了一个保留点,只要后面的任何一个INSERT操作失败,事务处理就能回退到这里。
在SQL Server中,检查一个名为@@ERROR的变量,看操作是否成功。若@@ERROR返回一个非0值,表示有错误发生,事务处理返回到保留点。若整个事务处理成功,发布COMMIT以保留数据。