保存点

1.语法

保存点-stmt:

SAVEPOINT savepoint-name

发布stmt:

RELEASE SAVEPOINT savepoint-name

回滚stmt:

ROLLBACK TRANSACTION TO SAVEPOINT savepoint-name

2.保存点

SAVEPOINT 是一种创建事务的方法,类似于 BEGINCOMMIT,除了 SAVEPOINT 和 RELEASE 命令被命名并且可以嵌套。

SAVEPOINT 命令用一个名字开始一个新的事务。事务名称不必是唯一的。SAVEPOINT 可以在BEGIN ... COMMIT之内或之外启动。当 SAVEPOINT 是最外层的保存点并且它不在BEGIN ... COMMIT中时,其行为与 BEGIN DEFERRED TRANSACTION 相同。

ROLLBACK TO 命令将数据库的状态恢复到相应的 SAVEPOINT 之后的状态。请注意,与普通的ROLLBACK命令(没有 TO 关键字)不同,ROLLBACK TO 命令不会取消事务。ROLLBACK TO 命令不是取消事务,而是在开始时再次重新启动事务。然而,所有介入的 SAVEPOINT 都被取消。

RELEASE 命令类似于 SAVEPOINT 的COMMITRELEASE 命令导致所有保存点返回并包括最近的具有匹配名称的保存点,从事务堆栈中删除。内部事务的 RELEASE 不会导致任何更改写入数据库文件;它只是从事务堆栈中删除保存点,这样就无法再回滚到这些保存点。如果 RELEASE 命令释放最外层的保存点,使事务堆栈变空,则 RELEASE 与COMMIT相同。COMMIT命令可用于释放所有保存点并提交事务,即使事务最初是由 SAVEPOINT 命令而不是BEGIN启动的命令。

如果 RELEASE 命令中的保存点名称与事务堆栈中当前的任何保存点都不匹配,则不会释放任何保存点,数据库不变,并且 RELEASE 命令返回错误。

请注意,内部事务可能会提交(使用 RELEASE 命令),但随后其工作会被外部事务中的 ROLLBACK 撤消。电源故障或程序崩溃或操作系统崩溃将导致最外层事务回滚,撤消在该外层事务中发生的所有更改,甚至是 RELEASE 命令应该“提交”的更改。在最外层的事务提交之前,内容实际上并没有提交到磁盘上。

有几种考虑 RELEASE 命令的方法:

  • 有些人认为 RELEASE 等同于 SAVEPOINT 的 COMMIT。这是一种可以接受的观点,只要记住内部事务提交的更改稍后可能会被外部事务中的回滚撤消。

  • RELEASE 的另一种观点是,它将命名事务合并到它的父事务中,这样命名事务和它的父事务就变成了同一个事务。在 RELEASE 之后,命名事务及其父事务将一起提交或回滚,无论它们的命运如何。

  • 还可以将保存点视为事务时间轴中的“标记”。在此视图中,SAVEPOINT 命令创建一个新标记,ROLLBACK TO 命令将时间线倒回到命名标记之后的某个点,而 RELEASE 命令从时间线中擦除标记而不实际对数据库进行任何更改。

3.交易嵌套规则

最后启动的事务将是第一个提交或回滚的事务。

BEGIN命令仅在事务堆栈为空时才有效,换句话说,如果没有待处理的事务。如果调用BEGIN命令时事务堆栈不为空,则该命令失败并出现错误。

COMMIT命令提交所有未完成的事务并将事务堆栈留空。

RELEASE 命令从最近添加到事务堆栈的内容开始,并及时向后释放保存点,直到它释放具有匹配保存点名称的保存点。先前的保存点,甚至具有匹配保存点名称的保存点,都没有改变。如果 RELEASE 命令导致事务堆栈变空(如果 RELEASE 命令从堆栈释放最外层的事务),则事务提交。

不带 TO 子句的ROLLBACK命令回滚所有事务并将事务堆栈留空。

带有 TO 子句的 ROLLBACK 命令将时间倒退的事务回滚到具有匹配名称的最近的 SAVEPOINT。具有匹配名称的 SAVEPOINT 保留在事务堆栈中,但在创建该 SAVEPOINT 之后发生的所有数据库更改都将回滚。如果 ROLLBACK TO 命令中的 savepoint-name 与堆栈上的任何 SAVEPOINT 都不匹配,则 ROLLBACK 命令会失败并出现错误并保持数据库状态不变。