Postgres无法创建唯一索引,密钥重复

Rob*_*sen 6 sql postgresql alter-table

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

ALTER TABLE quizzes ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT false;
Run Code Online (Sandbox Code Playgroud)

但是,我收到以下错误:

ERROR:  could not create unique index "quizzes_pkey"
DETAIL:  Key (id)=(10557462) is duplicated.
Run Code Online (Sandbox Code Playgroud)

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

SELECT id FROM quizzes WHERE id = 10557462;
 id 
----
(0 rows)
Run Code Online (Sandbox Code Playgroud)

事实上,似乎已经以某种方式跳过了id:

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

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

Rob*_*sen 9

我已经接受了@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;
Run Code Online (Sandbox Code Playgroud)

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

ALTER TABLE quizzes ADD COLUMN deleted BOOLEAN NOT NULL DEFAULT false;
Run Code Online (Sandbox Code Playgroud)


Cra*_*ger 7

我怀疑您预先存在索引损坏或可见性问题.

当你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;
Run Code Online (Sandbox Code Playgroud)

将揭示元组确实存在.

请先阅读并阅读此维基页面.完成后,请检查您的版本.您是否正在运行或曾经运行过早于9.3.9的PostgreSQL 9.3版本?特别是作为复制品,然后被提升?如果是这样,那可能会解释它,因为已知的multixact错误已修复:

否则,很难说发生了什么.有必要pageinspectpg_controldata输出时使用,也可能在引用那些堆页面的b-tree页面上查看问题堆页面.