事务控制即管理DML 语句所做的更改,和将DML 语句分组为事务。一般情况下,应用程序设计人员都关注事务控制,以便工作能按逻辑单元来完成,且数据能保持一致。
事务控制涉及使用下面的语句:
COMMIT 语句结束当前事务,并使在事务中执行的所有更改都具有持久性。提交还会清除在事务中的所有保存点,并释放事务锁。
ROLLBACK 语句将取消当前事务中所做的工作;它导致所有自上次提交或回滚以来的数据更改被丢弃。ROLLBACK TO SAVEPOINT语句将撤消自上次保存点以来所做的更改,但不会结束整个事务。
SAVEPOINT语句标识在事务中您可以稍后回滚到的点。
事务名称
事务名称是一个由用户指定的可选标记,作为工作中正在执行的事务中的一个提示。你使用SET TRANSACTION … NAME语句来为事务命名,如果要用它,则它必须是事务的第一个语句。
事务名称提供了以下优点:
有助于监测长时间运行的事务,并解决可疑的分布式事务。
您可以在应用程序中查看事务名称及其相应事务 ID。例如,数据库管理员可以在监视系统活动时,在Oracle 企业管理器 (企业管理器)中查看事务名称。
数据库将事务名称写入事务的审计重做记录,因此您可以使用 LogMiner 来搜索在重做日志中的特定事务。
可以使用事务名称在 V$TRANSACTION之类的数据字典视图中查找特定的事务。
活动事务
活动事务即是已开始但尚未提交或回滚的事务。
在事务提交或回滚之前,事务对数据所做的更改是暂时的。在事务结束之前,数据的状态如下所示:
Oracle 数据库已在系统全局区(SGA)中生成撤消数据信息。
撤消数据包含由事务中的SQL 语句所更改的数据旧值。
Oracle 数据库已在SGA 的联机重做日志缓冲区中生成了重做信息。
重做日志记录包含数据块和撤消块的更改。
已经对 SGA中的数据库缓冲区进行了更改。
已提交事务所做的数据更改,存储在 SGA 的数据库缓冲区中,但不一定会立即由数据库写入器写入数据文件。磁盘写入可能会在提交之前或之后发生。
数据更改所影响的行已被锁定。
其他用户不能更改受影响的行中的数据,也不能查看未提交的更改。
保存点
保存点是事务上下文中的一个由用户声明的中间标记。在内部,此标记将被解析为一个SCN。保存点将长事务划分为多个更小的部分。
如果你在一个长事务中使用保存点,则您就可以在之后将事务中执行的工作回滚到当前时间之前,却又在事务中声明的某个保存点之后。因此,如果您出了错,您不需要重新提交所有每个语句。
回滚到保存点
在未提交事务中回滚到某个保存点,意味着该指定的保存点之后所做的任何更改都将被撤消,但它并不意味着事务本身的回滚。当一个事务回滚到一个保存点时,将执行以下操作:
1 Oracle 数据库将只回滚在该保存点之后运行的语句。
2 Oracle 数据库保留在ROLLBACK TO SAVEPOINT语句中指定的保存点,但随后的所有保存点都将丢失。
3 Oracle 数据库释放在指定保存点之后获取的所有表锁和行锁,但保留在该保存点之前获取的所有数据锁。
事务仍处于活动状态,并可以继续。
排队事务
取决于当时的场景,之前在等待被锁定资源的事务,在回滚到保存点后,可能仍处于阻塞状态。一个事务被另一个事务阻塞时,它会在阻塞事务后面排队,因此整个阻塞事务必须提交或回滚,被阻塞的事务才能得以继续。
事务回滚
未提交事务的回滚,将撤消已由事务中的SQL 语句执行过的任何数据更改。事务回滚后,事务中所做工作的影响就不再存在。
对未引用任何保存点的整个事务的回滚, Oracle 数据库执行下列操作:
通过使用相应的撤销段,撤消事务中所有 SQL 语句所做的所有更改
每个活动事务的事务表条目包含一个指向该事务的所有撤消数据 (与应用顺序相反)的指针。数据库从撤销段中读取数据,反转其操作,然后将撤消条目标记为已应用。因此,如果一个事务插入行,则其回滚删除行。如果一个事务更新行,则其回滚反转这个更新。如果一个事务删除一个行,则其回滚重新插入该行。
释放由事务持有的所有数据锁
清除在事务中的所有保存点
结束事务
回滚的持续时间与被修改的数据量成正比。
事务提交
提交结束当前事务,并使事务中执行的所有更改持久化。
当一个事务提交时,将发生以下操作:
为提交生成系统更改号 (SCN)。
在关联的回滚表空间的内部事务表中记录已提交的事务。分配相应的唯一事务SCN,并将其记录在事务表中。
日志写入器 (LGWR)进程将重做日志缓冲区中的剩余重做日志条目写入到在线重做日志中,并将事务SCN写入到在线重做日志中。这个原子事件是提交事务的本质所在。
Oracle 数据库释放在行和表上持有的锁。
还在排队等待由未提交事务持有的锁的用户,现在可以继续他们的工作了。
Oracle 数据库删除保存点。
Oracle 数据库执行一个提交清理。
如果包含已提交的事务的被修改数据块仍处于SGA中,也没有其他会话正在对他们进行修改,则数据库从该块中删除与锁相关的事务信息。理想情况下,COMMIT会清理该数据块,以便后续的SELECT操作不必再执行此任务。
注意:
由于数据块清理会生成重做,所以查询可能生成重做,并因此导致在下一个检查点期间该数据块会被写入。
Oracle数据库将事务标记为完成
事务提交后,用户可以查看所做的更改。
通常,提交是一个快速的操作,而与事务大小无关。提交的速度不会随着在事务中修改的数据的大小的增大而增加。提交的最长部分是由 LGWR 执行的物理磁盘I/O。然而,LGWR 所用的时间量却减少了,因为它一直在在后台以增量方式写出重做日志缓冲区中的内容。
默认行为是, LGWR 必须将重做数据同步地写入联机重做日志,而事务必须等到被缓冲的重做数据被写到磁盘上之后,提交操作才能返回到用户。但是,为取得更低的事务提交延迟,应用程序开发人员可以指定重做被异步写入,以便事务不需要等待重做被写入磁盘,就可以立即从COMMIT调用返回。