每个表都有几个由系统隐式定义的系统列。因此,这些名称不能用作用户定义列的名称。(注意,这些限制与名称是否为关键字无关;给名称加引号也不能绕过这些限制。)你其实不必关心这些列的细节,只需要知道它们存在即可。
oid行的对象标识符(对象 ID)。只有使用WITH OIDS创建表,或创建时设置了default_with_oids配置变量,才存在此列。该列的类型是oid(与列同名);关于该类型的更多信息,参见Section 8.19。
tableoid包含该行的表的 OID。对于从继承层次(见Section 5.9)中查询数据的场景,这一列尤其方便,因为如果没有它,就很难判断一行究竟来自哪个具体表。tableoid可以与pg_class的oid列连接,以取得表名。
xmin插入该行版本的事务 ID。(行版本是某一行的一个具体状态;对同一逻辑行的每次更新都会创建一个新的行版本。)
cmin插入事务中的命令标识符(从0开始)。
xmax删除事务的标识(事务 ID);对于未删除的行版本则为 0。对于一个可见的行版本,该列也可能是非零值。这通常表示删除事务尚未提交,或者一次删除尝试被回滚了。
cmax删除事务中的命令标识符,或者为0。
ctid行版本在其表中的物理位置。注意尽管ctid可以被用来非常快速地定位行版本,但是一个行的ctid会在被更新或者被VACUUM FULL移动时改变。因此,ctid不适合用作长期行标识符。应使用 OID,或者更好地使用用户定义的序列号,来标识逻辑行。
OID 是 32 位的量,由整个集簇共用的单个计数器分配。在大型或长期运行的数据库中,该计数器可能发生回卷。因此,除非采取了确保唯一性的措施,否则不应假定 OID 唯一。如果需要标识表中的行,强烈建议使用序列生成器。不过,只要采取一些额外的预防措施,也可以使用 OID:
对于使用 OID 标识行的每个表,都应在其 OID 列上创建唯一约束。有这样的唯一约束(或唯一索引)时,系统会确保不生成与已有行相同的 OID。(当然,这只有在表的行数小于 232(40 亿)时才有可能;实际上,表的大小最好远小于此值,否则性能可能受影响。)
绝不能假定 OID 在不同表之间也唯一;如果需要数据库范围的标识符,应将tableoid与行 OID 组合使用。
当然,相关表必须以WITH OIDS创建。从PostgreSQL 8.1 开始,默认值是WITHOUT OIDS。
事务 ID也是 32 位的量。在一个长期运行的数据库中,事务 ID 可能会回卷。只要采取适当的维护措施,这并不是致命问题,详见Chapter 24。不过,从长期来看(超过十亿个事务)依赖事务 ID 的唯一性是不明智的。
命令标识符也是 32 位的量。这为单个事务中的SQL命令数设置了一个硬上限: 232(40 亿)。在实践中,这个限制并不是问题 — 注意,这里限制的是SQL命令的数量,而不是处理的行数。另外,只有真正修改数据库内容的命令才会消耗命令标识符。