我已经完成了这项工作,Postgres(以及 Discourse!)似乎都很满意。
我手动清理了它们,并根据需要使用 ** 模式使 URL 唯一。这可能只是一个无害的缓存,我可以删除重复项,但我不想冒险。
在我的例子中,只有一个索引,所以重建所有索引可能有点过度,但说实话,我感觉好多了,因为我知道我抓住了所有东西。
在几次重建失败的运行之后,每次运行大约需要 30 秒并报告一个问题,这是我的 SQL 魔术,可以立即获得问题项目的完整列表:
discourse=# select topic_id, post_id, url, COUNT(*) from topic_links GROUP BY topic_id, post_id, url HAVING COUNT(*) > 1 order by topic_id, post_id;
topic_id | post_id | url | count
----------+---------+-------------------------------------------------------+-------
19200 | 88461 | http://hg.libsdl.org/SDL/rev/**533131e24aeb | 2
19207 | 88521 | http://hg.libsdl.org/SDL/rev/44a2e00e7c66 | 2
19255 | 88683 | http://lists.libsdl.org/__listinfo.cgi/sdl-libsdl.org | 2
19255 | 88683 | http://lists.libsdl.org/**listinfo.cgi/sdl-libsdl.org | 2
19523 | 90003 | http://twitter.com/Ironcode_Gaming | 2
(5 rows)
(此查询中剩余 5 个有问题项,仅作示例。)
然后我会查看每个帖子,看看有什么以及如何修复:
select * from topic_links where topic_id=19255 and post_id=88683
然后修复其中一个:
update public.topic_links set url='http://lists.libsdl.org/__listinfo.cgi/**sdl-libsdl.org' where id=275100;
直到我把所有需要修复的东西都修完。 ![]()
我可能可以用一些内部连接魔术(或者一点 Ruby)在一个查询中完成所有这些工作,但我不是专家,而且手动完成这项工作花费的时间并不是几个小时。但说实话,这确实很繁琐。 ![]()
然后我运行了 REINDEX DATABASE discourse;,没有 CONCURRENTLY,只是为了简单起见,删除了我之前遗漏的几个 ccnew* 索引,然后我就搞定了。
网站一直在线,没有停机时间。
无论这是否必要,我绝对觉得我的数据现在更安全了,而且我不会走向某个未宣布的未来灾难。
感谢您给我指明了方向来解决这个问题,@pfaffman!