51.5. 索引唯一性检查

PostgreSQL使用唯一索引来强制SQL唯一约束,唯一 索引实际上是不允许多条记录有相同键值的的索引。一个支持这个特性的访问方法要 设置pg_am.amcanunique为真。目前,只有b-tree 支持它。

因为MVCC,必须允许重复的条目物理上存在于索引之中:该条目可能指向某个逻辑 行的后面的版本。实际想强制的行为是,任何 MVCC 快照都不能包含两条相同的索引 键字。这种要求在向一个唯一索引插入新行的时候分解成下面的几种情况:

此外,根据上面的规则进行唯一性检查之前,访问方法必须重新检查刚被插入的行是 否仍然"活跃",如果已经因为事务的提交而"钉死了",那么不应当发出任何错误。这 种情况不可能出现在插入同一个事务中创建的行的时候。但是在CREATE UNIQUE INDEX CONCURRENTLY的过程中是可能的。

要求索引访问方法自己进行这些测试,这就意味着它必须检查堆,以便查看那些根据 索引内容表明有重复键字的任意行的提交状态。这样做毫无疑问地很难看并且也不是 模块化的,但是这样可以节约重复的工作:如果进行额外的一次探测,而后面的索引 查找冲突行的的动作实际上是和查找插入新行的索引记录重复的动作。并且,没有很 显然的方法来避免冲突条件,除非冲突检查是插入新索引条目的整体动作的一部分。

如果唯一行性约束是可推迟的,这就更加复杂。我们需要能够向新行插入索引记录, 但推迟违反唯一性的错误直到声明的最后或者更迟的时候。为了避免对索引不必要 的重复搜索,索引访问方法应该在最初插入时做一次初步的唯一性检测。如果这个 结果表明记录里确定没有冲突了,就完成了。否则,我们会在该强制限制的时候安 排一个复核出现。(Note that for this purpose, "live" actually means "any tuple in the index entry's HOT chain is live".) To implement this, the aminsert function is passed a checkUnique parameter having one of the following values: