PG12 中索引损坏,如何修复?

很抱歉再次打扰,我遇到了一个非常奇怪的问题:

discourse=# REINDEX SCHEMA CONCURRENTLY public;
ERROR:  could not create unique index "index_tags_on_name_ccnew"
DETAIL:  Key (name)=(chronicillness) is duplicated.

我推测可以通过 @riking 上面建议的解决方案来修复,但我无法弄清楚如何修改语法以适应我的情况。:frowning:

1 个赞

请参见:

https://twitter.com/petervgeoghegan/status/1264325695997538304?s=20

https://twitter.com/petervgeoghegan/status/1264404749899534338?s=20

因此,如果您遇到此错误,可以采取以下两种措施:

  1. 您可以绕过该问题……在这种情况下,tags 表中存在一行重复数据,其名称为 chronicillness

    1. 执行数据探索器查询以搜索相关行:select * from tags where name = 'chronicillness'

    2. 删除重复项:

      ./launcher enter app
      rails c
      Tag.find_by(id: ID_YOU_FOUND_IN_DATA_EXPLORER).destroy
      
  2. 如果您有数据库的备份以及希望与 Peter 分享的详细信息……请通过私信或 PG 邮件列表与 Peter 分享。

8 个赞

我有一份由 Discourse 生成的 PostgreSQL 10 备份,这会有帮助吗?我能否直接从归档中提取 PostgreSQL 部分并发送?

我不确定……Peter 可能需要的只是你停止数据库,然后复制包含数据库的文件夹的全部内容。

最好的办法是给他发电子邮件确认一下。

2 个赞

好的,我会给他发封邮件来弄清楚这件事 :slight_smile:

注意:我在数据探索器中运行 SQL 时得到了以下结果

id name topic_count created_at updated_at pm_topic_count target_tag
1710 chronicillness 2 2019-12-03T17:49:17.395Z 2019-12-03T17:49:17.395Z 0 NULL

执行

Tag.find_by(id: 1710).destroy

能解决问题吗?

2 个赞

哦……索引是基于 LOWER(name) 的。

请这样运行查询:

select * from tags where name ilike 'chronicillness'

您应该会得到 2 行结果。

2 个赞
select * from tags where name ilike 'chronicillness'
id name topic_count created_at updated_at pm_topic_count target_tag
329 chronicillness 12 2017-08-22T00:17:38.824Z 2017-08-22T00:17:38.824Z 0 NULL
1710 chronicillness 2 2019-12-03T17:49:17.395Z 2019-12-03T17:49:17.395Z 0 NULL

标签名称之间会不会是 -
我在这看到了两个标签:chronicillness 和 chronic-illness。

1 个赞

那么问题就出在这里……我想你会删除 1710。之后会有两个主题缺少该标签。

3 个赞
#<Tag:0x00005607bb92cf48
 id: 1710,
 name: "chronicillness",
 topic_count: 0,
 created_at: 2019-12-03 17:49:17 UTC +00:00,
 updated_at: 2019-12-03 17:49:17 UTC +00:00,
 pm_topic_count: 0,
 target_tag_id: nil
>

为什么我觉得这像是个没有任何关联的小矮人?

删除标签后出现了更多问题!

discourse=# REINDEX SCHEMA CONCURRENTLY public;
WARNING: 无法并发重新索引无效的索引 "public.tags_pkey_ccnew",已跳过
WARNING: 无法并发重新索引无效的索引 "public.index_tags_on_name_ccnew",已跳过
WARNING: 无法并发重新索引无效的索引 "public.index_tags_on_lower_name_ccnew",已跳过
WARNING: 无法并发重新索引无效的索引 "pg_toast.pg_toast_309322_index_ccnew",已跳过
ERROR: 无法创建唯一索引 "index_tags_on_name_ccnew1"
DETAIL: 键 (name)=(time-management) 重复。
1 个赞

同样的修复方法 :slight_smile: 你需要重复这个过程。

1 个赞

我就是这么做的。不过那些警告没问题吧?我不需要担心那些对吧?

是的,所有警告都是正确的。你的索引已损坏,需要先修复。

3 个赞

所以所有的复制索引现在都已清除,我在重新索引时只剩下这些警告:

discourse=# REINDEX SCHEMA CONCURRENTLY public;
WARNING:  cannot reindex invalid index "public.tags_pkey_ccnew" concurrently, skipping
WARNING:  cannot reindex invalid index "public.index_tags_on_name_ccnew" concurrently, skipping
WARNING:  cannot reindex invalid index "public.index_tags_on_lower_name_ccnew" concurrently, skipping
WARNING:  cannot reindex invalid index "public.tags_pkey_ccnew1" concurrently, skipping
WARNING:  cannot reindex invalid index "public.index_tags_on_name_ccnew1" concurrently, skipping
WARNING:  cannot reindex invalid index "public.index_tags_on_lower_name_ccnew1" concurrently, skipping
WARNING:  cannot reindex invalid index "pg_toast.pg_toast_309322_index_ccnew" concurrently, skipping
WARNING:  cannot reindex invalid index "pg_toast.pg_toast_309322_index_ccnew1" concurrently, skipping
REINDEX

是否需要采取某些措施来消除这些警告,还是我们只能接受这些警告的存在?

1 个赞

这让我感到困惑……我们的索引名称中没有以 ccnew 结尾的……这些是你手动创建的吗?

1 个赞

我认为这些是在从 PostgreSQL 10 迁移到 12 时使用的,因为我看到几乎所有遇到索引问题的用户都提到了这些。例如:
https://meta.discourse.org/t/postgresql-12-update/151236/208?u=itsbhanusharma

https://meta.discourse.org/t/postgresql-12-update/151236/237?u=itsbhanusharma

编辑:来源是 PostgreSQL 官方文档

在这种情况下,推荐的恢复方法是删除无效索引,然后再次尝试执行 REINDEX CONCURRENTLY。在处理过程中创建的并发索引,其名称以 ccnew 结尾;如果是未能删除的旧索引定义,则以 ccold 结尾。可以使用 DROP INDEX 删除无效索引,包括无效的 TOAST 索引。

4 个赞

哎呀……正确的索引是否也已经存在于表中?

我想你可以使用数据资源管理器列出表上的索引。

如果正确的索引已经存在,那么你可以直接删除这些有问题的索引。

2 个赞

让我检查一下。我会向您汇报。

1 个赞

因此,索引似乎确实存在

问题索引的重复索引也存在,并添加了 ccnewccnew1

我不知道如何检查这些索引是否有效,但如果删除它们是一个可行的选项,我很乐意删除并重新建立索引。

编辑:按此处建议的方式使用 DROP INDEX 会有效吗?

2 个赞

是的,全部删掉……不知道它们怎么跑到那儿的……你应该使用 DROP INDEX

./launcher enter app
rails c
DB.exec('drop index tags_pkey_ccnew1')
6 个赞