【问题标题】:Changing column type in Postgres leads to pg_attrdef warnings在 Postgres 中更改列类型会导致 pg_attrdef 警告
【发布时间】:2018-02-26 16:04:03
【问题描述】:

我们正在尝试将 numeric(10,2) 列类型更改为 numeric(17,2) 类型。当我们用幼稚的方法来做这件事时:

ALTER TABLE table_a ALTER COLUMN col_a SET DATA TYPE numeric(17,2);

我们收到不理解的警告:

WARNING:  1 attrdef record(s) missing for rel table_a
WARNING:  generating possibly-non-unique OID for "pg_attrdef"

列类型确实正确更改为numeric(17,2)(至少\d table_a 告诉我们),我看不出结果表有任何问题,但警告仍然存在。

我们的表定义类似于:

                         Table "public.table_a"
         Column          |          Type          | Collation | Nullable | Default
-------------------------+------------------------+-----------+----------+---------
 col_a                   | numeric(10,2)          |           | not null | 0.00

在查阅了 postgres 文档后,我们通过首先删除 Default 约束来尝试另一列:

ALTER TABLE table_a ALTER COLUMN col_b DROP DEFAULT;
ALTER TABLE table_a ALTER COLUMN col_b SET DATA TYPE numeric(17,2);
ALTER TABLE table_a ALTER COLUMN col_b SET DEFAULT 0.00; 

导致更多警告:

WARNING:  2 attrdef record(s) missing for rel table_a
WARNING:  generating possibly-non-unique OID for "pg_attrdef"

正如您在对另一列运行查询后所见,我们现在在 pg_attrdef 中缺少 2 条记录。 运行查询时,警告似乎会持续存在并随机显示。

我们检查了pg_attrdef 表,看看是否可以发现任何发现adbin 内部表示中的:location 字段已设置为-1

adrelid | 37294
adnum   | 37
adbin   | {FUNCEXPR :funcid 1703 :funcresulttype 1700 :funcretset false :funcvariadic false :funcformat 2 :funccollid 0 :inputcollid 0 :args ({CONST :consttype 1700 :consttypmod -1 :constcollid 0 :constlen -1 :constbyval false :constisnull false :location -1 :constvalue 6 [ 24 0 0 0 0 -127 ]} {CONST :consttype 23 :consttypmod -1 :constcollid 0 :constlen 4 :constbyval true :constisnull false :location -1 :constvalue 4 [ 6 0 17 0 0 0 0 0 ]}) :location -1}
adsrc   | 0.00

但是编译它:

select pg_get_expr(pa.adbin, 'table_a'::regclass) from pg_attrdef pa where adrelid = 37294 and adnum = 37;

工作并返回正确的0.00 值。

一些进一步的背景信息:该表由 Hibernate 生成,列定义如下:

@Column(nullable = false, columnDefinition = "Decimal(10,2) default '0.00'")
private Double col_a = 0.0;

我正在 PostreSQL 10.0 数据库上运行查询,但想稍后在 8.4 数据库上运行。

有人可以帮助我们弄清楚这些警告的含义以及我们如何避免它们吗?

【问题讨论】:

    标签: sql postgresql hibernate


    【解决方案1】:

    您的服务器上的 pg_catalog.attrdef 表发生了一些事情,因此丢失了 attrdef 的 oid 列上应该存在的唯一索引。

    你可以看到这里出现的警告https://github.com/postgres/postgres/blob/master/src/backend/catalog/catalog.c#L312

    我认为您发出的语句正在尝试设置默认值,因此它们正在写入 attrdef 表。 Postgres 有一个内置假设,即目录表将在 oid 列上具有唯一索引,并在缺少索引时输出警告。我无法在我的 v10 机器上重新创建,所以我认为有人在您的特定实例上删除了唯一索引。

    似乎缺少的索引称为“pg_attrdef_oid_index”,因此如果 pg_catalog.pg_class 中没有该索引,则存在问题。

    除了您看到的警告之外,可能没有其他后果。

    尼尔

    【讨论】:

    • 非常感谢您的回答。我会将问题标记为已解决,但遗憾的是我无法测试您的答案。我注意到我在进行迁移时以管理员用户身份连接,但不是数据库用户,因此这可能是一个问题。我也可以从头开始重新创建数据库。在重新创建数据库并使用数据库所有者进行迁移后,它可以在没有警告的情况下工作。如果此问题再次发生,我将首先尝试重新创建您提到的索引。
    猜你喜欢
    • 1970-01-01
    • 2017-01-05
    • 1970-01-01
    • 2020-02-24
    • 1970-01-01
    • 2018-03-25
    • 2015-07-31
    • 2011-03-09
    • 1970-01-01
    相关资源
    最近更新 更多