アップグレード中に重複キー値がテーブルの一意制約に違反

こんにちは、皆さん。私が管理しているあるフォーラムで奇妙な問題が発生しています。

アップグレード中に、管理画面のアップグレードページかターミナル上で失敗し、以下のエラーが表示されました。

--------------------------------------------------------------------------------
1 件のマイグレーションに失敗しました!

デフォルトのマイグレーションに失敗しました
#<ActiveRecord::RecordNotUnique: PG::UniqueViolation: エラー: 重複するキー値が一意制約 "index_screened_ip_addresses_on_ip_address" に違反しています
詳細: キー (ip_address)=(10.0.0.0/8) は既に存在します。

幸いにも、フォーラムは壊れていません。./launcher restart app コマンドで復旧できました(以前、再起動後に空白ページが表示された際には ./launcher destroy app / ./launcher start app で助かったことがあります)。したがって、緊急事態ではありませんが、いくつかの指針が欲しいと思い投稿しました。

データベースを調査することにしました。いくつかのログらしきものとして IP 10.0.0.0/8 への参照がありましたが、screened_ip_addresses テーブルには重複は見当たりません。

--
-- TOC エントリ 6829 (クラス 0 OID 382198)
-- 依存関係: 657
-- 名前: screened_ip_addresses のデータ; タイプ: TABLE DATA; スキーマ: public; オーナー: -
--

COPY public.screened_ip_addresses (id, ip_address, action_type, match_count, last_match_at, created_at, updated_at) FROM stdin;
236	10.0.0.0/8	2	0	\N	2020-05-24 19:44:41.587257	2020-05-24 19:44:41.587257
237	192.168.0.0/16	2	0	\N	2020-05-24 19:44:47.150337	2020-05-24 19:44:47.150337
239	172.16.0.0/12	2	0	\N	2020-05-24 19:44:57.347656	2020-05-24 19:44:57.347656
240	fc00::/7	2	0	\N	2020-05-24 19:45:02.270948	2020-05-24 19:45:02.270948
261	154.71.107.147	1	0	\N	2020-06-05 13:15:17.718236	2020-06-07 00:27:57.204765
257	154.126.107.81	1	0	\N	2020-06-02 09:51:31.191431	2020-06-07 00:27:58.538628
259	197.1.186.242	1	0	\N	2020-06-05 08:39:52.218198	2020-06-07 00:27:58.985867
258	89.158.72.7	1	0	\N	2020-06-02 20:44:41.584317	2020-06-07 00:27:59.542337
260	196.179.229.13	1	0	\N	2020-06-05 08:39:52.227515	2020-06-07 00:28:00.288445
238	127.0.0.0/8	2	0	\N	2020-05-24 19:44:52.369958	2020-05-24 19:44:52.369958

フォーラム管理者は、/admin/logs/screened_ip_addresses ページでいくつかの IP を削除し、いくつか追加したと教えてくれました。しかし、私がこの IP に手を加えたとは思えません。奇妙なことに、この IP が追加されたのは 14 日前(私が最後にアップグレードした時期、おそらく PostgreSQL のアップグレード時)と表示されていますが、このフォーラムは 2015 年からのものです。他のフォーラムでは、作成日と照合されているようですが。

つまり、テーブルが少し混乱しているのでしょうが、実際にはそうは見えないのです。

SQL が苦手なので、あまり運試しはしたくありません。安全にアップグレードするための手順について、何か指針が欲しいです :raised_hands:

/admin/logs/screened_ip_addresses ページを整理すべきでしょうか?それとも、このテーブルや他のテーブルのエントリを削除(purge)しようとするべきでしょうか?

インデックスが破損しているようです。破損したインデックスに関する他のトピックも参照してみてください。

まず、インデックスの再構築を試すことができます。また、インデックスが正常に機能すると仮定しているため、多くの検索では重複エントリが見つからない点にご注意ください。

ありがとうございます。おそらく、以下のような手順でしょうか?

cd /var/discourse
./launcher enter app
su postgres
psql
\connect discourse
REINDEX SCHEMA CONCURRENTLY public;

もし、システム側でインデックスに問題がないと判断されるため、この方法が機能しない場合、このテーブルのサイズを考慮すると、以下の解決策は現実的でしょうか?

TRUNCATE public.screened_ip_addresses

その後、再インデックスを実行し、手動でそれらの IP を再度追加する、という手順でよろしいでしょうか?

スマホからなので、自分でマニュアルを読んでください。ただし、public.screened_ip_addresses のみ再構築することをお勧めします。そうすると、競合に関するエラーが発生するはずです。

ありがとう、コマンドを実行しましたが、エラーの言及はありませんでした。数時間後に再ビルドを試して、確認します

編集:再インデックスは何も効果はありませんでした

1 つのマイグレーションに失敗しました!

デフォルトのマイグレーションに失敗しました
#<ActiveRecord::RecordNotUnique: PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_screened_ip_addresses_on_ip_address"
DETAIL:  Key (ip_address)=(10.0.0.0/8) already exists.
>

アプリを再起動し、/admin/logs/screened_ip_addresses のすべての IP を削除して、正常にアップグレードしました。

IP は戻ってきました。手動で追加する必要はありませんでした

少し慎重になりすぎたかもしれませんが、これは私のフォーラムではないので、何かを壊したくなかったのです。@pfaffman さん、お手伝いありがとうございます!

次回同じことが起きたかどうかはわかりませんが、少なくとも修正方法がわかったので安心です

このトピックに関する最終更新です。前回は管理/アップグレードページからアップグレードしました。今回は確実にするために、ターミナルから再構築を行いました。マイグレーションの問題はありませんでした。問題なく完了しました。

問題が解決したことを確認しました :raised_hands: