So viele defekte Benutzer aufgrund einer beschädigten Datenbank

Ich habe ein echtes Problem mit vielen meiner Benutzer. Die Benutzer sind im Admin-Bereich so zu sehen:

Wenn ich jedoch versuche, ihre E-Mail-Adresse einzusehen, wird mir nichts angezeigt. Außerdem führt ihr öffentliches Profil auf einen 404-Fehler.

Soweit ich das übersehe, sind alle diese Benutzer nahezu inaktiv (sie sind zwar im Sinne einer Aktivierung aktiv, aber in Bezug auf ihre Aktivität im Forum inaktiv). Ich vermute daher, dass dies durch einen fehlerhaften automatischen Entfernungsprozess für inaktive Benutzer in der sehr fernen Vergangenheit verursacht wurde.

Eine weitere Sache, die mir auffällt:

Wenn ich sie deaktiviere und dann wieder aktiviere, werden sie behoben!

Wenn ein Benutzer eine bestimmte Zeit lang inaktiv ist (standardmäßig 730 Tage), wird er automatisch deaktiviert. Die Einstellung finden Sie in Ihrem Dashboard unter Einstellungen/Benutzer – scrollen Sie fast bis zum Ende nach unten. Dort werden Sie es sehen. Es ist jedoch nicht notwendig, Änderungen nur um der Änderung willen vorzunehmen. Wenn sich diese Benutzer seit zwei Jahren nicht eingeloggt haben, ergibt es keinen Sinn, sie wieder zu aktivieren, es sei denn, sie tauchen wieder auf. :wink:

Nein. Mein Problem ist nicht das. Im Dashboard steht, dass die Benutzer aktiviert sind.

Sieht ähnlich aus wie das Problem, das ich habe. Könntest du prüfen, ob die betroffenen Namen Duplikate oder „sehr ähnliche Übereinstimmungen

Ja, betroffene Nutzer gehören zu den sehr beliebten Benutzernamen. Daher schlägt Discourse einen ähnlichen Benutzernamen vor. Ich melde Nutzer über die API an. Ich erhalte also einen Benutzernamen vom Nutzer, prüfe ihn dann gegen die Discourse-API und falls er bereits vergeben ist, verwende ich automatisch den Vorschlag von Discourse.

Übrigens haben wir mit Hilfe von @RGJ das Problem auf diese beiden Bedingungen eingegrenzt:

Zusätzlich ist das Problem, das @hosna hat, eindeutig ein Problem auf Datenbankebene. Es scheint eine Art von Beschädigung in der users-Tabelle vorzuliegen. Das Kopieren des Inhalts in eine neue Tabelle löst diese Probleme.

Trotzdem habe ich in @hosnas Datenbank zwei Vorkommen des Problems von @bartv festgestellt (das waren die beiden Duplikate vor dem 22. September, und beide hatten einen Punkt im Benutzernamen), aber ich bin mir nicht sicher, ob diese beiden Probleme zusammenhängen. Sie weisen lediglich die gleichen Symptome auf.

Klingt nach einem beschädigten Datenbankindex. REINDEX TABLE users sollte das Problem lösen.

Was ist mit doppelten Benutzernamen? Ich habe viele gleiche Benutzernamen, die von zwei verschiedenen Benutzern verwendet werden.

Das Problem wird hier anerkannt:

Das ist wahrscheinlich eine Nebenwirkung eines beschädigten Indexes. Möglicherweise müssen Sie diesen manuell bereinigen, bevor die Neuindizierung funktioniert.

Können Sie erklären, wie es zu einem beschädigten Index kommen kann, um dies in Zukunft zu verhindern?

Hardwarefehler, ein Bug in Postgres… schwer zu sagen. Das passiert einfach.

Außer dass das unmöglich ist, da der Index beschädigt ist.
Dieser Befehl erledigt den Trick:

# Erstellen Sie eine temporäre Tabelle ohne Constraints und kopieren Sie den Inhalt hinein
create table users_test (like users);
insert into users_test select * from users;

# Entfernen Sie doppelte Benutzernamen (groß-/kleinschreibungsabhängig), die Duplikate stammen nach dem 22. September
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' ;

# Entfernen Sie doppelte Benutzernamen (groß-/kleinschreibungsunabhängig), die Duplikate stammen nach dem 22. September
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' ;

# Zwei weitere Probleme bleiben, löschen Sie sie einzeln
delete from users_test where id in (184534,130826);

# Erstellen Sie eine neue Tabelle mit Constraints und kopieren Sie die Benutzer hinein
create table users_clean (like users including indexes);
insert into users_clean select * from users_test;

Benennen Sie dann users in users_old und users_clean in users um.

Ich möchte hier kurz anmerken, dass dies deine Datenbank noch stärker beschädigen könnte als die defekten Benutzer!

Wir stecken nun mitten in einem Upgrade fest, da viele Constraints immer noch auf users_old verweisen, nachdem wir die Tabelle umbenannt haben. Dieses Problem trat erst einige Tage nach der Anwendung dieser anscheinend unvollständigen Lösung auf. Außerdem reicht like users including indexes nicht aus (es wird beispielsweise die id-Sequenz ignorieren).

Du hast absolut recht, ich erinnere mich tatsächlich daran, dass ich die Constraints nach dem Umbenennen der Tabellen neu erstellen musste. Entschuldige bitte dieses wichtige Versäumnis.

Aus meinen Notizen:

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);

und heutzutage auch:

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

Und als wichtiger Hinweis: verwende dies nur, wenn du absolut weißt, was du tust!

Dies scheint tatsächlich mit dem übereinzustimmen, was wir nach der Abfrage von pg_catalog nach Constraints gefunden haben, die users_old betreffen.

Außerdem fällt mir ein, dass including defaults zumindest erforderlich ist, um die Registrierung nicht zu unterbrechen.

Danke für die Korrektur!