OID
一个 OID 是 PostgreSQL 用作数据库对象唯一标识符(主键)的数据类型。 OID 数据类型实现为一个无符号 32 位整数。
历史用法
在 PostgreSQL 7.2 之前,OID 是强制性的,而在 PostgreSQL 8.1 之前,OID 默认包含在用户表的行中。这提供了区分其他完全相同的表行的潜在唯一标识符的边际优势,但这种唯一性不能保证,因为 OID 计数器可能会达到数据类型 32 位容量的上限并回绕。
在 PostgreSQL 8.1 和 PostgreSQL 11 之间的版本中,仍然可以通过在表定义中指定 WITH OIDS,或设置 配置文件参数 default_with_oids 来为用户表启用 OID。
如果启用,在 psql 中执行 INSERT 后,最近更新的 OID 将显示并存储在变量 LASTOID 中。但是,除非该表是显式使用 OID 创建的,否则此值通常为零。
postgres=# CREATE TABLE oidtest (id int) WITH OIDS; CREATE TABLE
postgres=# INSERT INTO oidtest VALUES(1); INSERT 10992082 1
postgres=# SELECT oid, id FROM oidtest; oid | id ----------+---- 10992082 | 1 (1 row)
从表中移除OID
源自较早的 PostgreSQL 版本且默认启用 OID 的表可以使用 ALTER TABLE ... SET WITHOUT OIDS 移除这些 OID,但请注意,与普通列移除不同,这将需要完整的表重写。
OID与系统目录表
在 PostgreSQL 11 及更早版本中,系统目录表上的 OID 是特殊的“隐藏”列,需要显式选择,例如 SELECT oid, * FROM pg_class。
PostgreSQL 12 的 OID
从 PostgreSQL 12 开始,不再可能为用户表启用 OID。此外,它们现在被视为系统表上的普通列,并且始终可见。
有关更多信息,请参阅提交 578b2297。
OID 的分配
从 16384 开始的 OID 由 PostgreSQL 自动分配(该值由 src/include/access/transam.h 中的常量 FirstNormalObjectId 定义)。
16384 以下的 OID 保留供系统使用。
目前,1-9999 之间的 OID 保留用于手动分配给系统目录条目;其中 8000-9999 保留用于开发目的(根据提交 09568ec3,9000 以上的 OID 保留供分叉使用)。
10000-11999 之间的 OID 用于 genbki.pl 自动生成的对象;12000 至 16383 之间的 OID 将用于引导过程中创建的对象。
脚本 src/include/catalog/unused_oids 可用于显示可用的 OID,甚至提供建议使用哪个 OID,例如:
$ src/include/catalog/unused_oids 4 - 9 111 388 - 389 560 - 583 786 - 789 811 - 816 1137 ... 6122 - 8431 8434 - 8455 8457 - 8594 8597 - 9743 9745 - 9999 Patches should use a more-or-less consecutive range of OIDs. Best practice is to start with a random choice in the range 8000-9999. Suggested random unused OID: 9004 (740 consecutive OID(s) available starting here)
有关更多详细信息,请参阅文档部分 OID Assignment。
OID 与 filenode
在检查 PostgreSQL 的磁盘文件结构时,乍一看,与表关联的文件名可能似乎对应于 pg_class 中的表 OID。然而,这并非总是如此:文件名由 filenode 标识,在正常情况下,filenode 最初与 OID 相同(注意:根据 src/backend/access/transam/xlog.c 中的注释,在崩溃情况之后存在一些特殊情况,此时可能并非如此),但它可以更改,例如在完整的表重写之后。
示例
一些 OID 在其自然环境中
postgres=# \d pg_trigger Table "pg_catalog.pg_trigger" Column | Type | Collation | Nullable | Default ----------------+--------------+-----------+----------+--------- oid | oid | | not null | tgrelid | oid | | not null | tgname | name | | not null | tgfoid | oid | | not null | tgtype | smallint | | not null | tgenabled | "char" | | not null | tgisinternal | boolean | | not null | tgconstrrelid | oid | | not null | tgconstrindid | oid | | not null | tgconstraint | oid | | not null | tgdeferrable | boolean | | not null | tginitdeferred | boolean | | not null | tgnargs | smallint | | not null | tgattr | int2vector | | not null | tgargs | bytea | | not null | tgqual | pg_node_tree | | | tgoldtable | name | | | tgnewtable | name | | | Indexes: "pg_trigger_oid_index" UNIQUE, btree (oid) "pg_trigger_tgrelid_tgname_index" UNIQUE, btree (tgrelid, tgname) "pg_trigger_tgconstraint_index" btree (tgconstraint)
注意:上面的示例取自 PostgreSQL 12;在早期版本中,第一个 oid 列将不可见。
参考资料
- PostgreSQL documentation: Object Identifier Types
- PostgreSQL documentation: OID Assignment
- PostgreSQL documentation: OID Reference Lookup
有用链接
- OIDs demoted to normal columns: a glance at the past - 2019 blog entry
