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

SQL Anywhere 12.0.0 (中文) » SQL Anywhere 服务器 - SQL 的用法 » 使用事务和隔离级别 » 锁定的工作方式

 

更新过程中的锁定

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

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

  2. 在表上获取意图写表锁(如果尚未持有)。

    1. 标识要更新的候选行。当扫描行时,将它们锁定。缺省锁定行为如隔离级别和一致性所述。

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

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

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

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

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

  6. 如果对行中的任何外键值进行了变更,则会在主表上获取一个共享模式锁,并按照插入过程中的锁定中概述的插入新外键值的过程进行操作。同样,按照 WAIT_FOR_COMMIT 的过程进行操作(如果适用)。

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

最后一步之后,任何 AFTER UPDATE 触发器都可能触发。COMMIT 后,服务器将通过确保此事务生成的遗孤数为 0 来验证参照完整性,并释放所有的锁。

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

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