Click here to view and discuss this page in DocCommentXchange. In the future, you will be sent there automatically.

SQL Anywhere 12.0.1 » SQL Anywhere 服务器 - SQL 的用法 » 事务和隔离级别 » 锁定的工作方式

 

更新过程中的锁定

数据库服务器使用以下过程修改一条特定记录中包含的信息。与插入相同,所有事务都将执行以下一系列的操作,而无论其隔离级别为何。

  1. 在表上获取共享模式锁(如果尚未持有)。

  2. 在要更新的每个表上获取意图写表锁(如果尚未持有)。

    1. 对于要更新的每个表,如果该表具有触发器,则根据需创建 OLD 和 NEW 值的临时表。

    2. 标识要更新的候选行。当扫描行时,将它们锁定。

      在隔离级别 2 和 3,会出现与缺省锁定行为不同的以下差异:将获取意图写行级锁定而非读锁定,并且可能会在最终被拒绝作为更新候选行的行上获取意图写锁定。

    3. 对于在步骤 2.a 中标识的每个候选行,遵循其余的顺序。

  3. 在受影响的行上放置写锁定。

  4. 按照每个 UPDATE 语句,更新每个受影响的列值。

  5. 如果索引值被更改,请添加新索引条目。会保留行的原始索引条目,但会将其标记为已删除。持有长期插入锁时插入新值的新索引条目。服务器将校验索引唯一性(如果适当)。

  6. 如果发生了唯一性违规现象,则会创建一个临时“保存的”表来保存行的旧值和新值。将旧值和新值复制到保存的表中,然后删除基表行。不会触发任何 DELETE 触发器。延迟步骤 7 到 9,直到结束逐行处理为止。

  7. 如果对行中的任何外键值进行了变更,则会在主表上获取一个共享模式锁,并按照插入新外键值的过程进行操作。

    同样,按照 WAIT_FOR_COMMIT 的过程进行操作(如果适用)。

  8. 如果该表是参照完整性关系中的主表,且关系的 UPDATE 操作不是 RESTRICT,则确定外表中受影响的行(通过以下操作:首先在外表上获取共享模式锁,然后在每个表上获取意图写表锁),然后在所有受影响的行上获取写锁定,并根据需要修改各行。请注意,此过程可能分多级进行参照完整性约束的嵌套层次。

  9. 根据需要触发 AFTER ROW 触发器。

完成最后一步之后,如果需要一个保存的临时表,现在可将保存的临时表中的每一行插入到基表中(但不会触发 INSERT 触发器)。如果行插入操作成功完成,将执行步骤 7-9 并将旧值和新值分别复制到 OLD 临时表和 NEW 临时表中,以允许任何 AFTER STATEMENT UPDATE 触发器正确处理修改的所有行。处理完保存的所有行之后,会按顺序触发 AFTER STATEMENT UPDATE 触发器。COMMIT 后,服务器将通过确保此事务生成的遗孤数为 0 来验证参照完整性,并释放所有的锁。

修改列值可能需要执行大量操作。如果您要修改的列不属于主键或外键,数据库服务器需要完成的工作量会少得多。如果要修改的列不包含在索引中(此索引或显式创建,或因为您已将该列声明为唯一的而隐式创建),需要完成的工作量还会更少。

UPDATE 操作过程中的参照完整性校验操作并不比 INSERT 过程中的校验操作简单。实际上,更改主键的值时,就可能会产生遗孤。插入替换值时,数据库服务器必须再次检查是否产生了遗孤。

 另请参见