分类: Oracle
2009-09-08 01:32:18
3.2 使用SAVEPOINT(1)
试验目标
在完成这个试验之后,你能够:在PL/SQL 语句块中使用COMMIT 、ROLLBACK 和SAVEPOINT 使用事务,意味着可以把程序分解为多个可管理的单元。把事务分解为多个更小的元素,这是一种常见的标准实践,可以保证应用程序只会保存正确的数据。最初, 任何应用程序必须连接到数据库,才能获取数据。当用户在应用程序中执行DML 语句时,其他用户看不到这个变更请求,必须等到执行COMMIT 或者ROLLBACK 语句。Orcale 保证数据的读一致性视图。在执行COMMIT 或者ROLLBACK 语句之前,所有被插入或者修改的数据都保存在内存中,只适用于当前用户。修改的数据行被当前用户锁定,在解锁之前,其他用户不能进行更新。COMMIT 或者ROLLBACK 语句会释放这些锁。使用SAVEPOINT 命令标识事务的多个保存点,可以更加灵活和容易地控制事务。
COMMIT 会把事务中的事件永久化。
ROLLBACK 会删除事务中事件。
除此之外,可以使用SAVEPOINT 来控制事务。在PL/SQL 语句块中,从一个SAVEPOINT
到另一个SAVEPOINT,可以定义事务。使用SAVEPOINT 命令可以把事务分解为多个单元,这样的话,在一个PL/SQL
语句块中,有些单元可以被提交(保存到数据库),有些单元可以回滚(撤销操作),等等。
提示请注意,事务和PL/SQL 语句块之间的差别。PL/SQL 语句块的开始和结束并不一定意味着事务的开始和结束。
为演示事务控制的价值,下面讨论一个两步骤数据操作过程。例如,例设Student 数据库中有预备课程的所有课程的费用需要提升10% 。同时,没有预备课程的所有课程的费用需要降低10% 。这是一个两步骤处理过程。如果某步骤处理成功,但是第2 个步骤没有处理成功,则数据库中有关课程的成本数据就是不一致的。由于这种调整是基于百分比的,无法跟踪哪部分课程调整是成功的,哪部分是不成功的。
在下面的例子中,使用一个PL/SQL 语句块对课程表中成本项执行更新操作。在第1 个步骤中(这部分代码中注释很明显,标识每个更新步骤),没有预备课程的课程成本项降低10% 。在第2 个步骤中,有预备课程的课程成本项提高10% 。
假设第1 个更新语句执行成功,但是由于网络失效,第2 个更新语句执行失败。现在,课程表中数据就不一致了,因为没有预备课程的课程成本项已经降低,但是有预备课程的课程成本项没有调整。为防止出现这种情况, 更新语句必须集成到一个事务中。这样的话,可以保证两个更新操作语句要么都成功,要么都失败。
通常,事务会把表示工作逻辑单元的SQL 语句集成起来。这个事务起始于先前事务之后的第1 条SQL 语句,或者连接到数据库之后的第1 条SQL 语句。事务结束于COMMIT 或者ROLLBACK 语句。
1. COMMIT
当向数据库提交COMMIT 语句时,这个事务就结束了,并且如下结果都会发生:
事务所做的所有工作都会永久化。
其他用户可以看到这个事务所做的数据变更。
该事务拥有的所有锁被释放。COMMIT 语句的语法如下所示:
单词WORK 是可选的,使用它的目的是改进可读性。在事务提交之前,只有执行当前事务的用户才能看到自己会话中所做的数据变更。
假设用户A 对STUDENT 表执行如下命令,这个表存在于另外一个模式,但是有个学生的公开同义词:
然后,用户A 执行如下命令:
如果用户B 再次执行相同的查询,则不能看到相同的结果了。
在上述范例中,存在两个会话:用户A 和用户B。用户A 在STUDENT 表中插入一条记录。用户B 查询STUDENT 表,但是没有得到用户A 所插入的那条记录。用户B 看不到这条记录的原因是,用户A 尚未提交所做的工作。当用户A 提交这个事务时,用户B 再次执行这个查询时,就会看到用户A 所插入的记录。