5.4. 系统列

每个表都有几个由系统隐式定义的“系统列”。因此,这些名称不能用作用户定义列的名称。 (请注意,这些限制与名称是否是关键字是分开的;引用名称将使您无法逃避这些限制.)您实际上并不需要担心这些列;您不必担心。只知道它们存在。

  • oid

    • 行的对象标识符(对象 ID)。仅当使用WITH OIDS创建表或当时设置了default_with_oids配置变量时,此列才存在。此列的类型为oid(与列名称相同);有关该类型的更多信息,请参见Section 8.18
  • tableoid

包含该行的表的 OID。对于从继承层次结构中选择的查询(请参见Section 5.9),此列特别方便,因为如果没有它,则很难确定一行来自哪个表。可以将tableoidpg_classoid列连接起来以获得表名。

  • xmin

此行版本的插入事务的标识(事务 ID)。 (行版本是行的单独状态;行的每次更新都会为同一逻辑行创建一个新的行版本.)

  • cmin

插入事务中的命令标识符(从零开始)。

  • xmax

删除事务的标识(事务 ID),对于未删除的行版本为零。在可见行版本中,此列可能为非零。这通常表明删除事务尚未提交,或者尝试删除的操作已回滚。

  • cmax

删除事务中的命令标识符,或者为零。

  • ctid

行版本在其表中的物理位置。请注意,尽管ctid可用于非常快速地查找行版本,但是如果行VACUUM FULL被更新或移动了VACUUM FULL,则行ctid将会更改。因此,ctid作为长期行标识符没有用。应该使用 OID 或更好的用户定义序列号来标识逻辑行。

OID 为 32 位,并从单个群集范围的计数器分配。在大型或长期存在的数据库中,计数器可能会回绕。因此,除非您采取措施确保确实如此,否则认为 OID 是唯一的是不好的做法。如果需要识别表中的行,强烈建议使用序列生成器。但是,只要采取一些其他预防措施,也可以使用 OID:

  • 应该在每个表的 OID 列上创建一个唯一约束,将使用该 OID 来标识行。当存在这样的唯一约束(或唯一索引)时,系统注意不要生成与现有行匹配的 OID。 (当然,只有在表包含少于 232(40 亿)行的情况下才有可能,并且实际上表的大小最好远小于该行,否则性能可能会受到影响。)

  • OID 绝对不应在表之间是唯一的;如果需要数据库范围的标识符,请结合使用tableoid和行 OID。

  • 当然,有问题的表必须创建为WITH OIDS。从 PostgreSQL 8.1 开始,WITHOUT OIDS是默认值。

Transaction 标识符也是 32 位的数量。在寿命长的数据库中,事务 ID 可能会回绕。如果采取适当的维护程序,这不是致命的问题;有关详情,请参见Chapter 24。但是,长期依赖 TransactionID(超过十亿笔 Transaction)的唯一性是不明智的。

命令标识符也是 32 位量。这在单个事务中创建了 232(40 亿)条 SQL 命令的硬限制。实际上,此限制不是问题-请注意,此限制是针对 SQL 命令的数目,而不是处理的行数。同样,只有实际修改数据库内容的命令才会使用命令标识符。