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

SQL Anywhere 11.0.1 (中文) » SQL Anywhere 服务器 - SQL 的用法 » 创建数据库 » 使用事务和隔离级别 » 锁定的工作方式

 

插入过程中的锁定

INSERT 操作将创建新行。SQL Anywhere 在插入过程中利用多种类型的锁定以确保数据的完整性。对于以任何隔离级别执行的 INSERT 语句,都将发生以下一系列操作。

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

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

  3. 在页中找到未被锁定的位置以存储新行。为了减少锁定争用,服务器不会立即重新使用通过删除(但尚未被提交)行而变得可用的空间。可能会将新的页分配给表(且数据库文件可能会增大)以容纳新的行。

  4. 将所提供的任何值填入新行。

  5. 在要添加该行的表中放置一个插入锁。上文中已经讲过插入锁是独占的,因此,获取了该插入锁后,任何其它隔离级别 3 的事务都不能通过获取幻像锁来阻塞这个插入操作。

  6. 在新行上放置写锁定。获取写锁定后,会释放插入锁。

  7. 将行插入表中。现在,处于隔离级别 0 的其它事务第一次可以看到这一新行存在。然而,由于之前获取了写锁定,这些其它事务无法修改或删除新行。

  8. 更新所有受影响的索引并校验唯一性(如果适当)。主键值必须是唯一的。也可以将其它列定义为只包含唯一的值。如果这样的列存在,则需要校验唯一性。

  9. 如果该表是外表,则在主表上获取共享模式锁(如果尚未持有),并在主表中相匹配的主行上获取读锁定(如果插入的外键列值非 NULL)。数据库服务器必须确保主行在插入事务 COMMIT 后仍存在。方法是,在主行上获取一个读锁定。放置了这个读锁定后,任何其它事务仍可以读取该行,但都不能删除或更新该行。

    如果相应的主行不存在,则给出参照完整性约束违规。

最后一步之后,在该表上定义的任何 AFTER INSERT 触发器都可能触发。触发器中的处理遵循与应用程序相同的锁定行为。提交(假设满足所有的参照完整性约束)或者回退了事务后,会释放所有长期锁定。

唯一性

可以确保特定的一列或列组合中的所有值都是唯一的。数据库始终通过为唯一列构建索引(即使您没有显式创建)来执行此任务。

特别是,所有主键值都必须是唯一的。数据库服务器自动为每个表的主键构建索引。不要请求数据库服务器在主键上创建索引,因为这样做是多余的。

遗孤和参照完整性

通常,一个外键会参照另一个表中的一个主键或 UNIQUE 约束。如果该主键不存在,不符合要求的外键被称作遗孤。SQL Anywhere 会自动确保您的数据库中不包含任何遗孤。这个过程被称作校验参照完整性。数据库服务器通过计算遗孤数来校验参照完整性。

wait_for_commit

可以指示数据库服务器将参照完整性校验延迟到事务结束时。利用这种方式,可以插入包含外键的一行,然后再插入包含丢失的主键的主行。这两个操作必须在同一事务中发生。

要请求数据库服务器将参照完整性检查延迟到提交时,请将 wait_for_commit 选项的值设置为 On。缺省情况下,此选项被设置为 Off。要启用该选项,请发出以下命令:

SET OPTION wait_for_commit = On;

如果插入新外键值时服务器未找到匹配的主行,且 wait_for_commit 为 On,则服务器允许该行以遗孤的形式插入。对于孤立的外行,插入时会发生以下一系列步骤:

  • 服务器在主表上获取一个共享模式锁(如果尚未持有)。服务器还会在主表上获取一个意图写锁。

  • 服务器将代理行插入到主表中。并未向主表插入实际的行,但出于锁定目的,服务器会为该行生成一个唯一行标识符,并在此代理行上获取写锁定。随后,服务器会向主表的主键索引插入适当的值。

提交事务之前,数据库服务器将通过检查您的事务产生的遗孤数来校验是否保持了参照完整性。在每个事务结束时,遗孤数必须为零。