【问题标题】:Postgres could not create unique index, key is duplicatedPostgres 无法创建唯一索引,键重复
【发布时间】:2017-07-26 00:28:28
【问题描述】:

我正在尝试使用这个看似简单的 SQL 向我的 Postgres 9.3 数据库中的表添加一列:

ALTER TABLE quizzes ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT false;

但是,我收到以下错误:

ERROR:  could not create unique index "quizzes_pkey"
DETAIL:  Key (id)=(10557462) is duplicated.

奇怪的是,实际上 没有行 具有该 id(这是主键,所以它不应该有重复):

SELECT id FROM quizzes WHERE id = 10557462;
 id 
----
(0 rows)

事实上,这个 id 似乎被某种方式跳过了:

SELECT id FROM quizzes WHERE id > 10557459 ORDER BY id LIMIT 4;
    id    
----------
 10557460
 10557461
 10557463
 10557464
(4 rows)

为什么这会阻止我添加列,我该如何解决?

【问题讨论】:

  • 我不明白添加 deleted 列会如何导致唯一键违规。你确定那是正在运行的代码吗?
  • 是的,我确定。我在 psql 提示符下输入该代码并按 Enter。

标签: sql postgresql alter-table


【解决方案1】:

我怀疑您已经存在索引损坏或可见性问题。

当您ALTER TABLE ... ADD COLUMN ... DEFAULT ... 时,它会进行全表重写。这会重建所有索引,在此过程中注意到堆上的问题。

您可能会发现桌子上的VACUUM FULL 会产生相同的错误。

我期待

BEGIN;
SET LOCAL enable_indexscan = off;
SET LOCAL enable_bitmapscan = off;
SET LOCAL enable_indexonlyscan = off; 
SELECT ctid,xmin,xmax,id FROM quizzes WHERE id = 10557462;
ROLLBACK;

将揭示元组确实存在。

请先阅读this wiki page 并采取行动。完成后,检查您的版本。您是否正在运行或曾经运行过早于 9.3.9 的 PostgreSQL 9.3 版本?尤其是当时被提升的复制品?如果是这样,那可能是由于那里修复了已知的 multixact 错误:

否则,很难说发生了什么。有必要使用pageinspect、pg_controldata 输出查看问题堆页面,并可能查看引用这些堆页面的 b 树页面。

【讨论】:

  • 感谢您的回复。我运行了您建议的查询,确实有 5 行 ID 为 10557462。根据SELECT id, count(*) FROM quizzes GROUP BY id HAVING count(*) > 1;,这是唯一有重复的测验。除了对数据损坏 wiki 页面采取行动之外,还有其他建议吗?
【解决方案2】:

我接受了@Craig Ringer 的回答,因为没有它我永远无法解决问题。如果它对其他人有帮助,这是我用来解决问题的确切查询(幸运的是,可以删除重复项):

BEGIN;
SET LOCAL enable_indexscan = off;
SET LOCAL enable_bitmapscan = off;
SET LOCAL enable_indexonlyscan = off; 
DELETE FROM quizzes WHERE id = 10557462;
COMMIT;

之后,我原来的查询终于成功了:

ALTER TABLE quizzes ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT false;

【讨论】:

  • 就个人而言,我强烈建议您现在 pg_dump db(s)、pg_dumpall --globals-only,然后 initdb 替换空白 postgres 实例并恢复到其中。我不相信这个没有其他未被发现的问题。
猜你喜欢
  • 2021-06-22
  • 2014-12-29
  • 1970-01-01
  • 1970-01-01
  • 2015-03-22
  • 1970-01-01
  • 2019-12-04
  • 1970-01-01
  • 2013-09-13
相关资源
最近更新 更多