Столько сломанных пользователей из-за повреждённой базы данных

У меня возникла серьёзная проблема с многими моими пользователями. Пользователи отображаются в панели администратора следующим образом:

Однако, когда я пытаюсь раскрыть их адрес электронной почты, ничего не отображается. Кроме того, их публичные профили вызывают ошибку 404.

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

Ещё один момент, который я заметил:

Если я деактивирую, а затем активирую их, они исправляются!

Если пользователь неактивен в течение определённого времени (по умолчанию 730 дней), он автоматически деактивируется. Настройка находится в вашей панели управления в разделе Настройки/Пользователи, прокрутите страницу почти до самого низа. Именно там вы это увидите. Однако нет необходимости вносить изменения ради самих изменений. Если эти пользователи не входили в систему в течение 2 лет, нет смысла реактивировать их, если они снова не начнут появляться. :wink:

Нет. Моя проблема не в этом. В панели управления указано, что пользователи активированы.

Похоже на проблему, с которой я столкнулся. Можете проверить, есть ли в вашей базе данных дубликаты или «очень похожие совпадения» среди затронутых имен? Например, user.user и useruser.

Да, затронутые пользователи — это те, чьи имена пользователей очень популярны. Поэтому Discourse предлагает похожее имя пользователя. Я регистрирую пользователей через API: получаю имя пользователя от пользователя, затем проверяю его через API Discourse, и если оно уже занято, автоматически использую то, что предлагает Discourse.

Кстати, с помощью @RGJ мы сузили проблему до двух условий:

В дополнение к этому, проблема, с которой сталкивается @hosna, явно связана с уровнем базы данных. Похоже, что в таблице пользователей есть какая-то поврежденность. Копирование содержимого в новую таблицу решает эти проблемы.

Тем не менее, я заметил два случая проблемы @bartv в базе данных @hosna (это были два дубликата до 22 сентября, и у обоих в имени пользователя была точка), но я не уверен, связаны ли эти две проблемы между собой. У них просто одинаковые симптомы.

Похоже на повреждённый индекс базы данных. Команда REINDEX TABLE users должна решить проблему.

А что насчет дубликатов имен пользователей? У меня много одинаковых имен пользователей, используемых для двух разных пользователей.

Проблема признана здесь:

Это, скорее всего, побочный эффект повреждённого индекса. Возможно, вам потребуется вручную очистить его перед тем, как повторная индексация начнёт работать.

Можете ли вы объяснить, как может произойти повреждение индекса, и как предотвратить это в будущем?

Сбой оборудования, ошибка в Postgres… сложно сказать. Такое бывает.

Однако это невозможно, поскольку индекс повреждён.
Вот что поможет:

# создаём временную таблицу без ограничений и копируем в неё содержимое
create table users_test (like users);
insert into users_test select * from users;

# удаляем дубликаты имён пользователей с учётом регистра (дубликаты после 22 сентября)
delete from users_test where username in (
  select username 
  from users_test 
  group by username 
  having count(username)>1
) and created_at>'2019-09-22' ;

# удаляем дубликаты имён пользователей без учёта регистра (дубликаты после 22 сентября)
delete from users_test where lower(username) in (
  select lower(username) 
  from users_test 
  group by lower(username) 
  having count(lower(username))>1
) and created_at > '2019-09-22' ;

# осталось ещё две проблемы — удаляем их по отдельности
delete from users_test where id in (184534,130826);

# создаём новую таблицу с ограничениями и копируем в неё пользователей
create table users_clean (like users including indexes);
insert into users_clean select * from users_test;

Затем переименуйте users в users_old, а users_clean — в users.

Хочу вмешаться и сказать: это может ещё больше сломать вашу базу данных, чем повреждённые пользователи!

Мы теперь застряли посередине между обновлениями, так как множество ограничений всё ещё ссылаются на users_old после переименования таблицы. Эта проблема проявилась лишь через несколько дней после применения этого, очевидно, неполного исправления. Кроме того, команды like users including indexes недостаточно (например, она проигнорирует последовательность id).

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

Из моих заметок:

alter table poll_votes drop constraint fk_rails_b64de9b025;
alter table poll_votes add constraint fk_rails_b64de9b025 FOREIGN KEY (user_id) REFERENCES users(id);

alter table user_security_keys drop constraint fk_rails_90999b0454;
alter table user_security_keys add  constraint fk_rails_90999b0454 FOREIGN KEY (user_id) REFERENCES users(id);

А в наше время также:

alter table bookmarks drop constraint fk_rails_c1ff6fa4ac;
alter table bookmarks add  constraint fk_rails_c1ff6fa4ac FOREIGN KEY (user_id) REFERENCES users(id);

И важное предупреждение: используйте это только тогда, когда вы абсолютно уверены в том, что делаете!

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

Также помню, что параметр including defaults был как минимум необходим, чтобы не нарушить процесс регистрации.

Спасибо за исправление!