Дублирование ключа нарушает уникальное ограничение таблицы во время обновления

Всем привет, у меня возникла странная проблема с одним из форумов, который я поддерживаю.

Во время обновления на странице admin/upgrade или в терминале процесс завершился с ошибкой:

--------------------------------------------------------------------------------
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; Тип: ТАБЛИЦА ДАННЫХ; Схема: 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

Администратор форума сказал мне, что он очистил некоторые IP-адреса на странице /admin/logs/screened_ip_addresses и добавил новые. Но я сомневаюсь, что он трогал этот IP-адрес. Странно то, что система сообщает, что IP был добавлен 14 дней назад (это было время моего последнего обновления, вероятно, обновления PostgreSQL), хотя форум существует с 2015 года. На других форумах проверка проводится по дате создания.

Похоже, таблица немного повреждена, но на самом деле это не выглядит так.

Я не хочу слишком сильно рисковать, особенно потому, что я плохо разбираюсь в SQL. Поэтому я хотел бы получить рекомендации по процедуре, которой нужно следовать, чтобы гарантировать безопасное обновление :raised_hands:

Стоит ли мне очистить страницу /admin/logs/screened_ip_addresses, попытаться удалить записи из этой таблицы или из другой?

Похоже, индекс повреждён. Вы можете поискать другие темы, посвящённые повреждённым индексам.

Сначала попробуйте восстановить индекс. Также имейте в виду, что многие поисковые запросы не найдут дублирующиеся записи, так как они предполагают, что индекс работает корректно.

Спасибо, наверняка это будет что-то вроде этого?

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. Думаю, при этом возникнут ошибки из-за конфликтов.

Спасибо, я выполнил команду, ошибок не было. Попробую ещё раз собрать через несколько часов и посмотрю.

edit: ок, переиндексация ничего не сделала.

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.
>

Я перезапустил приложение, очистил все IP в /admin/logs/screened_ip_addresses и успешно обновился.

IP-адреса вернулись, добавлять их вручную не пришлось.

Возможно, я проявил слишком много осторожности, но раз это не мой форум, я не хотел ничего испортить. Спасибо @pfaffman за помощь!

В следующий раз посмотрю, повторится ли это, но хотя бы теперь я знаю, как это исправить.

Последнее обновление по этой теме: в прошлый раз я обновлялся через страницу admin/upgrade. В этот раз я хотел выполнить пересборку через терминал, чтобы убедиться. Проблем с миграцией не возникло. Всё прошло успешно.

Подтверждаю, что проблема закрыта :raised_hands: