2017-07-26 131 views
2

我想列在我的Postgres添加到表这个看似简单的SQL数据库9.3:的Postgres不能创建唯一索引,钥匙被复制

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) 

这是为什么阻止我添加一列,我怎么能解决这个问题?

+1

我不明白如何添加“已删除”列可能会导致唯一的密钥违规。你确定这是正在运行的代码吗? –

+0

是的,我确定。我在psql提示符下键入该代码并按Enter键。 –

回答

5

我怀疑你有预先存在的索引损坏或可见性问题。

当你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错误:

否则,很难说发生了什么。有必要使用pageinspectpg_controldata输出来查看问题堆页面,并且可能在b-tree页面引用这些堆页面。

+0

感谢您的回复。我运行了你建议的查询,而且确实有5行ID为10557462。根据'SELECT id,count(*)FROM测验GROUP BY id HAVING count(*)> 1;',这是唯一带有重复项的测验。除了在数据损坏维基页面上进行操作之外,还有其他建议吗? –

1

我接受了@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; 
+0

个人而言,我强烈建议你现在使用'pg_dump' db,sgdbt-only,然后initdb代替空白postgres实例并恢复到它。我不相信这一个没有其他未被发现的问题。 –