使用 pg_repack 从 PostgreSQL 中的表中删除 OID

问题描述 投票:0回答:1

我正在准备旧版 PostgreSQL 9.5 数据库进行升级。

我需要从表中删除 OID,而不需要长时间锁定表。我已经制定了一个似乎有效的策略,但我希望专家能够参与进来,因为我计划对系统表进行一些通常不被允许的操作。

在运行 pg_repack 之前,我执行以下修改:

mydata=# update pg_class set relhasoids = false where oid = 'some_schema.a_very_large_table_with_oids'::regclass;
UPDATE 1
mydata=# delete from pg_attribute where attrelid = 'some_schema.a_very_large_table_with_oids'::regclass and attname = 'oid';
DELETE 1
mydata=# \d+ some_schema.a_very_large_table_with_oids;
        Table "some_schema.a_very_large_table_with_oids"
 Column | Type | Modifiers | Storage  | Stats target | Description 
--------+------+-----------+----------+--------------+-------------
 k      | text | not null  | extended |              | 
 v      | text |           | extended |              | 
Indexes:
    "a_very_large_table_with_oids_pkey" PRIMARY KEY, btree (k)

mydata=# select oid,* from some_schema.a_very_large_table_with_oids;
ERROR:  column "oid" does not exist

到目前为止一切顺利。我可以插入更新和删除行,但磁盘上的表结构没有改变。我需要解决这个问题。

因此,在进行这些修改后,我使用 vanilla pg_repack 重新打包表。这会将数据复制到磁盘上的新表中,无需任何 oid。

在我开始对生产数据在线执行这些操作之前,我希望有一些专家关注这个过程,因为这是关键任务。

在非常大的表上,我们将在很长一段时间内处于这种不确定状态,其中 pg_class 和 pg_attribute 将进行强制修改,而 pg_repack 发挥其魔力。

如果插入/更新/删除似乎有效,有什么需要担心的吗?

在 pg_repack 运行时我在表上的插入/更新/删除似乎工作正常。

我还在附有烤面包桌的桌子上尝试过这个。乍一看一切似乎都井然有序。

这是一个破坏性操作,我没有使用规范的

ALTER TABLE ... SET WITHOUT OIDS
。如果我遗漏了一些细节(例如在备份恢复或复制期间),我想确保我不会给自己带来问题。

请指教。

postgresql postgresql-9.5 pg-repack
1个回答
0
投票

您想避免表重写,对吗?

您正在做的事情相当于 PostgreSQL 在

commit 6d1e361852
之前对 ALTER TABLE ... SET WITHOUT OIDS 所做的事情,除了您忘记在表上加
ACCESS EXCLUSIVE
锁,并且您不会使其他计划和缓存的元数据信息无效。会话有此表。

现在有一个原因,

ALTER TABLE ... SET WITHOUT OIDS
被更改重写表格;请参阅此错误报告此后续线程中的讨论。那里提到的问题在
pg_upgrade
之后不会影响您,但是如果您的表的元组中物理上有 OID,而 PostgreSQL 不希望有任何 OID,则可能会出现其他微妙的问题。这就是为什么
ALTER TABLE ... SET WITHOUT OIDS
被更改以重写表格的原因。

您期望运行 pg_repack 会物理上删除元组中剩余的 OID,但它不会,就像

VACUUM (FULL)
不会一样。两者都只是按原样复制现有元组。您必须执行类似
INSERT INTO newtab SELECT FROM oldtab
之类的操作,这将消除
oldtab
中的物理 OID,但相当于您想要避免的表重写。

您的目录操作将使表处于类似于 PostgreSQL 8.3 及更早版本中的

ALTER TABLE ... SET WITHOUT OIDS
的状态。现在
pg_upgrade
文档提到 9.2 及更高版本支持升级,并且在 commit e469f0aaf3 之前提到支持 8.4 及更高版本。虽然历史文档中没有明确提及以您的方式删除 OID 的表会构成问题,但这种情况显然是意外的,根本没有经过测试并且不受支持。您将来可能会遇到有趣的问题。我当然不会为我的数据库冒这个风险。

为了安全起见,通过重写表来正确删除 OID。

© www.soinside.com 2019 - 2024. All rights reserved.