保持游标

当使用事务日志记录时,GBase 8s 保证在事务结束时,可回滚在事务内所作的一切。要可靠地处理事务,数据库服务器通常应用下列规则:
  • 当事务结束时,关闭所有游标。
  • 当事务结束时,释放所有锁。
对于支持事务的大多数数据库系统,用于可靠地处理事务的规则都是正常的。然而,存在一些情况,随同游标使用标准事务是不可能的。例如,在没有事务的情况下,下列代码正常工作。然而,当添加事务时,关闭游标与同时使用两个游标发生冲突。
EXEC SQL DECLARE master CURSOR FOR 
          EXEC SQL DECLARE detail CURSOR FOR  FOR UPDATE
          EXEC SQL OPEN master;
          while(SQLCODE == 0)
          {
          EXEC SQL FETCH master INTO 
          if(SQLCODE == 0)
          {
          EXEC SQL BEGIN WORK;
          EXEC SQL OPEN detail USING 
          EXEC SQL FETCH detail 
          EXEC SQL UPDATE  WHERE CURRENT OF detail
          EXEC SQL COMMIT WORK;
          }
          }
          EXEC SQL CLOSE master;

在此设计中,使用一个游标来扫描表。选择了的记录用作更新不同的表的基础。问题在于,当将每一更新当做分开的事务处理时(如前一示例中伪代码所示),跟在 UPDATE 之后的 COMMIT WORK 语句关闭所有游标,包括主游标。

最简单的替代方案是将 COMMIT WORK 语句和 BEGIN WORK 语句分别移到最后一个语句和第一个语句, 这样,对整个主表的扫描就是一个大事务。将主表的扫描作为一个大事务来处理,有时是可能的,但如果需要更新许多行,它可变得不现实。锁的数目可能太大,并且在程序期间持有它们。

GBase 8s 数据库服务器支持的解决方案是将关键字 WITH HOLD 添加到主游标的声明。引用这样的游标作为持有游标,在不在事务结束时关闭。数据库服务器仍然关闭所有其他游标,且它仍然释放所有锁,但持有游标保持打开,直到显式地关闭它为止。

在您尝试使用持有游标之前,您必须确保了解此处描述的锁定机制,且您还必须了解正在并发地运行的程序。每当执行 COMMIT WORK 时,释放所有锁,包括放置在任何通过该持有游标访存的行上的任何锁。

对于对表的单向扫描,如果如您所愿地使用游标,则锁的移除无关紧要。然而,您可为任何游标指定 WITH HOLD,包括更新游标和滚动游标。在您这么做之前,您必须了解该事实的含义,即,在事务结束时,释放所有锁(包括对整个表的锁)。