将 PostgreSQL 从 9.4 升级到 12 时消除 OID

G_H*_*hat 13 postgresql upgrade

我目前在生产环境中运行 PostgreSQL 9.4,但我们正在服务器上进行操作系统升级,因此我认为可能是时候将 PostgreSQL 版本升级到最新版本 (12),以便我可以利用一些可用的新功能。然而,各个数据库中的一些表是很久以前构建的(例如,2008 年之前,至少在某些情况下很可能是 2000 年之前)。这些数据库包含许多使用 OID 的表(WITH OIDS=TRUE在定义中)。

此外,我还对大部分代码库进行了搜索,以查找任何表中对 OID 列的引用,并发现了几个实例,其中存在显式调用 OID 列的查询。幸运的是,这样的情况并不,而且大多数都是引用系统表(即,SELECT oid FROM pg_namespace...FROM pg_class)。

对从 9.4 数据库转储的数据运行pg_upgrade该过程会在此时停止,并断然声明直到数据库中没有 OID 后才会继续。据我所知,他们在过去的几个版本中一直在慢慢地逐步淘汰这些内容,而 12 版本使它们基本上变得无关紧要,但建议是在pg_upgrade继续之前完全删除 OID 列。我认为这对于一个几乎不相关的专栏来说是“矫枉过正”。

此时 - 我承认我还没有完全考虑到这一点 - 我想知道简单地“翻转”WITH OIDS受影响的表定义中的开关是否FALSE足以继续升级?如果翻转的话,现有的 OID 列是否仍是数据库结构的一部分(我认为会,但自动升级可以做一些有趣的事情)?

我意识到,在理想情况下,我希望最终从数据库中完全消除 OID。然而,作为一个单人 IT 部门,这必须“列入清单”以供以后评估。目前,我只是想让数据库在最新的 PostgreSQL 版本上启动并运行,同时我有机会这样做而不会立即影响操作。

小智 7

这是一个查询,可帮助查找具有该WITH OIDS集的所有表。它还生成要删除的 DDL。

    SELECT 'ALTER TABLE "' || n.nspname || '"."' || c.relname || '" SET WITHOUT OIDS;'
FROM pg_catalog.pg_class c
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
WHERE 1=1
  AND c.relkind = 'r'
  AND c.relhasoids = true
  AND n.nspname <> 'pg_catalog' 
order by n.nspname, c.relname;
Run Code Online (Sandbox Code Playgroud)


Lau*_*lbe 6

如果oid代码中引用了表的 s,则不能简单地删除它们。旧代码可能依赖于oid自动生成的标识符。这些列上是否有主键或其他索引?

在升级过程中保留oids 的一种方法是:

  • 升级之前,在旧数据库上:

    ALTER TABLE has_oids ADD newoid bigint NOT NULL;
    UPDATE has_oids SET newoid = oid;
    ALTER TABLE has_oids SET WITHOUT OIDS;
    
    Run Code Online (Sandbox Code Playgroud)
  • 升级后,在新数据库上:

    ALTER TABLE has_oids RENAME newoid TO oid;
    CREATE SEQUENCE has_oids_oid_seq OWNED BY has_oids.oid;
    ALTER TABLE has_oids ALTER oid SET DEFAULT nextval('has_oids_oid_seq');
    SELECT setval('has_oids_oid_seq', ???);
    
    Run Code Online (Sandbox Code Playgroud)

这里,是一个比表中???最高值更高的数字。oid

您还必须处理oid列上的索引或约束。