↑↓ 选择 ↵ 打开 ⌫ 改范围 完整检索页

pgsql.cc 提供对 postgresql.org 官网内容的中文翻译,由 Pigsty 团队维护。

受支持版本: 当前版本 (18) / 17 / 16 / 15 / 14
测试与开发版本: 19 / devel
不受支持的版本: 13 / 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1
历史版本PostgreSQL 8.1 已于 2010 年 11 月结束社区维护,本页译文保留供仍在使用旧版本的读者参考。新系统请看当前版本。

48.5. 索引唯一性检查 #

PostgreSQL 使用唯一索引来强制执行 SQL 唯一性约束;所谓唯一索引,就是不允许存在多个具有相同键值条目的索引。支持这一特性的访问方法会把 pg_am.amcanunique 设为真。(目前只有 B-树支持这一点。)

由于 MVCC 的存在,索引中在物理上总是必须允许存在重复条目:这些条目可能指向同一个逻辑行的连续版本。我们真正想强制的行为是,任何 MVCC 快照都不能同时包含两行拥有相同索引键的记录。在向唯一索引插入一行新数据时,必须检查以下几种情况:

  • 如果某一条冲突的有效行已被当前事务删除,那么这是允许的。(特别是,因为一次 UPDATE 总是在插入新版本前删除旧版本,这就允许对某一行执行不改变键值的 UPDATE。)

  • 如果某条冲突的行是由一个尚未提交的事务插入的,那么当前准备插入的事务必须等待,看看那个事务是否提交。如果它回滚,就不存在冲突;如果它提交并且没有再次删除那条冲突行,就发生了唯一性违背。(实际上,我们只是等待另一个事务结束,然后把可见性检查整个重新做一遍。)

  • 类似地,如果某条冲突的有效行是由一个尚未提交的事务删除的,那么当前准备插入的事务必须等待该事务提交或中止,然后重新执行测试。

我们要求索引访问方法自行应用这些测试,这意味着它必须深入堆中检查那些根据索引内容显示为具有重复键的行的提交状态。毫无疑问,这样做既丑陋又不够模块化,但它避免了重复工作:如果我们单独再做一次探测,那么在寻找新行索引条目插入位置时,查找冲突行的索引搜索实际上就会被重复执行。更何况,除非把冲突检查作为插入新索引条目动作的一个组成部分,否则也没有明显的方法可以避免竞争条件。

该方案的主要局限在于,它没有支持延迟唯一性检查的便捷方法。

提交更正

译文有误、术语不当或页面显示问题,请到译文仓库 pgsty/pgdoc 报告译文问题。 英文原文本身的问题,请在当前版本的对应页面向上游反馈;上游不再修订已结束维护的版本。