RETAINUPDATELOCKS 环境选项

RETAINUPDATELOCKS 环境选项可提高在包括 SELECT ... FOR UPDATE 语句的“动态的 SQL”应用中的并发性。如果会话正在使用 Committed Read、Dirty Read 或 Cursor Stability 隔离级别来启用(或禁用)SET ISOLATION 语句的 RETAIN® UPDATE LOCKS 子句,则此选项可修改当前的事务隔离级别在运行时的行为。

当为当前的隔离级别启用 RETAINUPDATELOCKS 环境选项时,在缺省情况下,数据库服务器保持在行上的更新锁,直到该事务结束。保持任何更新锁,直到提交或回滚该事务,不管定义了该隔离级别的 SET ISOLATION 语句是否包含了 RETAIN UPDATE LOCKS 关键字。当此选项设置为 ALL 或为当前的 GBase 8s 隔离级别的名称时(如果此级别为 Committed Read、Dirty Read 或 Cursor Stability),则此设置防止其他事务中的并发用户删除或更新您已在其上放置了更新锁,而您还未更新的行。

通过指定 NONE 为 RETAINUPDATELOCKS 设置,您禁用此特性并恢复缺省的锁定行为。 当 NONE 为设置时,除非已经通过显式地包括了 RETAIN UPDATE LOCKS 关键词的 SET ISOLATION 语句设置了隔离级别,数据库服务器在下一 FETCH 操作时,或当游标关闭时,释放该更新锁。

SET ENVIRONMENT RETAINUPDATELOCKS 语句对更新游标不起作用,如果 GBase 8s 隔离级别为 REPEATABLE READ 的话。 类似地,在作用域之外是已通过 SET TRANSACTION 语句设置了其隔离级别的事务,其定义符合 ANSI/ISO 的隔离级别,而不是 GBase 8s 隔离级别。(要获取更多关于 GBase 8s 和 ISO 隔离级别的信息,请参阅主题 对比 SET TRANSACTION 与 SET ISOLATION。)

RETAINUPDATELOCKS 选项接受可影响当前的 GBase 8s 隔离级别的五种设置中的任何一种,以及在 SET ENVIRONMENT 语句之后通过 SET ISOLATION 语句建立的隔离级别。对于除了 'NONE' 之外的每个设置,该设置的作用就是隐式地在 SET ISOLATION 规范中包括 RETAIN UPDATE LOCKS 关键字:

这些设置不区分大小写。例如,'ALL''all' 作用相同。

当发出 SET ENVIRONMENT RETAINUPDATELOCKS 语句时,它就生效(通过重置该会话环境)。可在事务的外部发出它。如果当前事务的隔离级别与在 RETAINUPDATELOCKS 关键字之后指定的设置相匹配,则当发出该语句时,新的设置可更改正在运行的事务的 RETAIN UPDATE LOCKS 行为。

例如,考虑下列 SET ENVIRONMENT 和 SET ISOLATION 语句:

BEGIN WORK; --开始第一个事务
      SET ENVIRONMENT RETAINUPDATELOCKS 'COMMITTED READ';
      SET ISOLATION TO COMMITTED READ LAST COMMITTED;
      SELECT ... FOR UPDATE ...
      ...
      COMMIT WORK;
      SET ENVIRONMENT RETAINUPDATELOCKS 'DIRTY READ';
      BEGIN WORK; --开始第二个事务
      SET ISOLATION TO COMMITTED READ LAST COMMITTED;
      SELECT ... FOR UPDATE ...
      ...
      COMMIT WORK; 
在上述的第一个事务中,SET ENVIRONMENT 语句中的 RETAINUPDATELOCKS 设置使得更新锁的保持成为 Committed Read 隔离级别的缺省的行为。因此,数据库服务器翻译第一个 SET ISOLATION 语句,其指定 Committed Read 但没有 RETAIN UPDATE LOCKS 子句,就好像它已经包括了那个子句:
SET ISOLATION TO 
        READ LAST COMMITTED RETAIN UPDATE LOCKS;

然而,由于在第二个事务中的 SET ENVIRONMENT RETAINUPDATELOCKS 语句指定 DIRTY READ 作为它的设置,它对第二个 SET ISOLATION 语句不起作用,其定义 Committed Read 隔离级别。对应于特定的 GBase 8s 隔离级别的每一设置仅影响使用相同隔离级别的事务中的更新锁。

但是在跨服务器 SELECT ... FOR UPDATE 分布式查询中,有些参与的服务器不支持更新锁保持,整个事务符合发出了该事务的会话的隔离级别。如果那个会话有启用的 RETAINUPDATELOCKS 选项生效,对于支持更新锁保持的服务器它也生效,但其他参与的服务器为了释放更新锁,遵循它们的缺省行为。

如果在其中发出语句的数据库不支持事务日志记录,则 SET ENVIRONMENT RETAINUPDATELOCKS 语句失败并报错 -26199。

sysdbopen( ) 过程

当您的会话连接到其中定义了 sysdbopen( ) 的数据库时,内建的 sysdbopen( ) 例程可发出 SET ENVIRONMENT RETAINUPDATELOCKS 语句,如下例中所示。
CREATE PROCEDURE PUBLIC.SYSDBOPEN()
          SET PDQPRIORITY 10;
          SET ENVIRONMENT RETAINUPDATELOCKS 'ALL';
          END PROCEDURE

在上述示例生效之后,它防止其他会话更改您已在其上放置了更新锁的行,以便于您可在当前事务中稍后再更新这些行。除非您在相同的会话之内发出另一 SQL 语句来禁用更新锁的保持,否则 sysdbopen( ) 发出的 SET ENVIRONMENT RETAINUPDATELOCKS 语句的作用保持,直到该会话结束为止。然而, sysdbopen( ) 指定的 RETAINUPDATELOCKS 值的会话内持续是特殊情况。任何其他 SPL 例程都可使用 SET ENVIRONMENT 语句来指定为 Committed Read、Dirty Read 或 Cursor Stability 事务隔离级别,或为 'ALL',指定更新锁保持,但仅在例程执行时保持它们的作用,而不是在例程退出之后。

重置缺省的更新锁行为

GBase 8s 早于版本 11.50.xC6 的版本中,最近执行的 SET ISOLATION 语句为随后的事务指定缺省值。如果最近的 SET ISOLATION 语句包括了 RETAIN UPDATE LOCKS 子句,则有必要为相同的隔离级别执行 SET ISOLATION 语句(但不带有 RETAIN UPDATE LOCKS 子句)来禁用更新锁的保持。然而,目前,如果 SET ENVIRONMENT RETAINUPDATELOCKS 已启用了保持,则您必须显式地运行 SET ENVIRONMENT RETAINUPDATELOCKS 'NONE' 语句来恢复不保持作为缺省的行为,如下例中所示。

BEGIN WORK;  --开始第一个事务
        SET ISOLATION TO COMMITTED READ LAST COMMITTED;
        SET ENVIRONMENT RETAINUPDATELOCKS 'COMMITTED READ';
        SELECT ... FOR UPDATE ...
        ...
        COMMIT WORK;
        BEGIN WORK;  --开始第二个事务
        SET ENVIRONMENT RETAINUPDATELOCKS 'NONE';
        SET ISOLATION TO COMMITTED READ LAST COMMITTED;
        SELECT ... FOR UPDATE ...
        ...

在上述第一个事务中,第一个 SET ENVIRONMENT 语句将当前事务的 Committed Read 隔离级别的行为更改为保持更新锁,即使在该事务之内按照词典顺序,建立了那个隔离级别的 SET ISOLATION 语句仍在 SET ENVIRONMENT 语句之前。通过此 SET ENVIRONMENT 语句对此隔离级别的 LAST COMMITTED 规范不起作用。

然而,按字面翻译第二个事务中的 SET ISOLATION 语句,因为通过第二个 SET ENVIRONMENT 语句将缺省的行为重置为了 NONE。

在高可用性集群中的更新锁保持

在高可用性集群环境中,RETAINUPDATELOCKS 选项仅在主服务器上有效。需要更新锁的保持的应用必须在主服务器上运行,如果它们包括 SET ENVIRONMENT RETAINUPDATELOCKS 语句的话。当从辅助服务器发出它时,该语句对锁定行为没有影响,且服务器返回错误。