Wiederherstellung fehlgeschlagen – konnte keinen eindeutigen Index erstellen

Hallo, die Wiederherstellung eines Backups schlägt mit folgendem Fehler fehl:

CREATE INDEX
FEHLER: konnte den eindeutigen Index "index_incoming_referers_on_path_and_incoming_domain_id" nicht erstellen
DETAIL: Schlüssel (path, incoming_domain_id)=(/m/search, 25) ist dupliziert.
AUSNAHME: psql fehlgeschlagen: DETAIL: Schlüssel (path, incoming_domain_id)=(/m/search, 25) ist dupliziert.

Ich habe ein ähnliches Thema gefunden, konnte aber nicht herausfinden, was zu tun ist: https://meta.discourse.org/t/getting-this-error-during-restore-could-not-create-unique-index/

Ich wäre dankbar für eine schrittweise Hilfe für Anfänger, um das Problem zu beheben.

Dieses Problem mit der Tabelle incoming_referers ist in letzter Zeit bereits einige Male aufgetaucht. Ich bin mir nicht sicher, warum gerade diese Tabelle Probleme verursacht, aber es scheint wahrscheinlich, dass die Probleme zusammenhängen. Vielleicht hat jemand anderes im Discourse-Team Ideen, was zur Erstellung der doppelten Datensätze führen könnte.

Haben Sie noch Zugriff auf die Site, auf der Sie die Sicherungsdatei erstellt haben? Wenn ja, besteht die Lösung darin, den doppelten Datensatz aus der Datenbank zu löschen und anschließend eine neue Sicherungsdatei zu erstellen. Dazu müssten Sie per SSH auf den alten Server zugreifen und in das Verzeichnis /var/discourse wechseln:

cd /var/discourse

Führen Sie dann aus:

./launcher enter app

Geben Sie dann mit folgendem Befehl die Rails-Konsole auf:

rails c

Sie sollten dann eine Eingabeaufforderung sehen, die ähnlich wie diese aussieht:

[1] pry(main)>

Versuchen Sie, den folgenden Befehl aus der Rails-Konsole auszuführen, und teilen Sie uns mit, was er zurückgibt:

IncomingReferer.where(path: "/m/search")

Es sollte ein Array mit zwei oder mehr Datensätzen zurückgegeben werden.

Vielen Dank.
Ich werde dies morgen ausführen und mich wieder melden.

Das stammt von der alten Installation – sieht aus wie nur ein Eintrag?

[1] pry(main)> IncomingReferer.where(path: "/m/search")
=> [#<IncomingReferer:0x00005638d834b130
  id: 5153,
  path: "/m/search",
  incoming_domain_id: 25>]
[2] pry(main)>

Edit: Habe es auch auf dem neuen Server versucht. Dort wird angezeigt:

[1] pry(main)> IncomingReferer.where(path: "/m/search")
=> []
[2] pry(main)>

Danke, dass du das überprüft hast! Das Ergebnis, das du erhalten hast, entspricht tatsächlich dem, was ich heute früher auf einer anderen Seite gesehen habe. Es ist ein lösbares Problem, aber ich werde versuchen, einen unserer Ingenieure dazu zu bewegen, sich anzusehen, was los ist.

Mein Hauptgrund für den Umzug der Server war, dass ich Debian 8 nutzte, dessen Support bald ausläuft. Im Zusammenhang mit diesem Wiederherstellungsproblem habe ich mich dafür entschieden, auf demselben Server auf Debian 9 zu aktualisieren. Dies war erfolgreich, was mir vorerst etwas Erleichterung verschafft hat.
Vielen Dank für Ihre Unterstützung.

Ersetzen Sie diese Zeile

Sie müssen eine Fuzzy-Suche durchführen, damit nicht davon ausgegangen wird, dass der Index funktioniert. Ein Prozentzeichen reicht wahrscheinlich aus, wenn es am Anfang steht, denke ich.

Sie können den zusätzlichen Eintrag einfach löschen. Um es richtig zu machen, müssen Sie jedoch die andere Tabelle aktualisieren, die mit dieser verknüpft ist. Ich muss es jedes Mal nachschlagen, da es ein paar verschiedene Tabellen gibt, die dies betreffen.

Dieses Problem wird Drittanbieter-Erweiterungen angelastet, was nicht sehr sinnvoll erscheint. Es scheint, als müsste es ein Fehler von PostgreSQL sein, aber ich weiß es nicht. Ich stoße ein paar Mal im Monat darauf, scheint es (Score) über eine Reihe von Sites.

Ich habe ebenfalls ein Problem mit doppelten Schlüsseln. Gibt es eine dokumentierte Lösung?

discourse=# REINDEX SCHEMA CONCURRENTLY public;
    ERROR:  could not create unique index "index_incoming_referers_on_path_and_incoming_domain_id_ccnew"
DETAIL:  Key (path, incoming_domain_id)=(/search/, 1905) is duplicated.

[1] pry(main)> IncomingReferer.where(path: "/m/search")
=> [#<IncomingReferer:0x0000557176d3f210 id: 44231, path: "/m/search", incoming_domain_id: 4>,
 #<IncomingReferer:0x0000557176d925c8 id: 42228, path: "/m/search", incoming_domain_id: 26>]

Obwohl ich meinen Server gerade direkt aktualisiert habe und daher nicht mehr auf einen neuen Server wiederherstellen werde, habe ich dies aus Neugier ausprobiert und konnte bei der Fuzzy-Suche keine Einträge finden:

[1] pry(main)> IncomingReferer.where(path: "%/m/search%")
=> []
[2] pry(main)> IncomingReferer.where(path: "%/m/search")
=> []
[3] pry(main)> IncomingReferer.where(path: "/m/search%")
=> []

Du musst LIKE verwenden, damit Platzhalter funktionieren:

IncomingReferer.where("path LIKE '%/m/search%'")

Das hat noch einige weitere doppelte Schlüssel zutage gebracht.

[1] pry(main)> IncomingReferer.where("path LIKE '%/m/search%'")
=> [#<IncomingReferer:0x0000557eaa7ed488 id: 408, path: "/m/search", incoming_domain_id: 26>,
 #<IncomingReferer:0x0000557eaabd80c0 id: 1508, path: "/m/search", incoming_domain_id: 45>,
 #<IncomingReferer:0x0000557eaabe3268 id: 2216, path: "/m/search", incoming_domain_id: 420>,
 #<IncomingReferer:0x0000557eaabe2f20 id: 3081, path: "/m/search", incoming_domain_id: 230>,
 #<IncomingReferer:0x0000557eaabe2c00 id: 33210, path: "/m/search", incoming_domain_id: 4>,
 #<IncomingReferer:0x0000557eaabe2908 id: 44231, path: "/m/search", incoming_domain_id: 4>,
 #<IncomingReferer:0x0000557eaabe27c8 id: 42228, path: "/m/search", incoming_domain_id: 26>]

Ich würde einfach alle doppelten Zeilen löschen… dieser Information ist wenig Wert beizumessen.

Gerne! Könntest du mir den richtigen Befehl nennen? Ich bin mit PostgreSQL nicht speziell vertraut, kenne aber SQL.

Das ist gut zu hören. Ich habe mühevoll die andere Tabelle aktualisiert, die auf diese verweist. Es ist eine enorme Last, da ich mir nie merken kann, wie sie hieß, also muss ich es immer wieder von vorne machen.

IncomingReferer.find(44231).destroy
IncomingReferer.find(42228).destroy

Das Entfernen dieser beiden Duplikate war erfolgreich, aber beim anschließenden Neuaufbau der Indizes traten neue Fehler auf. Ist dies ein schwerwiegendes Problem? Wie beheben wir das und löschen wir diese Zeile mit der Suche 3433?

[1] pry(main)> IncomingReferer.find(44231).destroy
=> #<IncomingReferer:0x000055734c65d8e8 id: 44231, path: "/m/search", incoming_domain_id: 4>
[2] pry(main)> IncomingReferer.find(42228).destroy
=> #<IncomingReferer:0x000055734cd81a70 id: 42228, path: "/m/search", incoming_domain_id: 26>
postgres=# \connect discourse
Sie sind jetzt mit der Datenbank "discourse" als Benutzer "postgres" verbunden.
discourse=# REINDEX SCHEMA CONCURRENTLY public;
WARNING:  cannot reindex invalid index "public.incoming_referers_pkey_ccnew" concurrently, skipping
WARNING:  cannot reindex invalid index "public.index_incoming_referers_on_path_and_incoming_domain_id_ccnew" concurrently, skipping
WARNING:  cannot reindex invalid index "pg_toast.pg_toast_2782645_index_ccnew" concurrently, skipping
ERROR:  could not create unique index "index_incoming_referers_on_path_and_incoming_domain_id_ccnew1"
DETAIL:  Key (path, incoming_domain_id)=(/search/, 3433) is duplicated.
CONTEXT:  parallel worker

Hier ist der Code, der die Erstellung verarbeitet… Das sollte es ordnungsgemäß handhaben, aber wir könnten es bei Bedarf auf einen ON CONFLICT-Insert aktualisieren?

Ich habe versucht, diese 4 Indizes manuell neu zu erstellen. Zwei waren erfolgreich, zwei sind fehlgeschlagen. Soll ich diese zwei doppelten Zeilen löschen?

discourse=# REINDEX INDEX CONCURRENTLY "public"."incoming_referers_pkey_ccnew";
REINDEX
discourse=# REINDEX INDEX CONCURRENTLY "public"."index_incoming_referers_on_path_and_incoming_domain_id_ccnew";
ERROR:  could not create unique index "index_incoming_referers_on_path_and_incoming_domain_id_cc_ccnew"
DETAIL:  Key (path, incoming_domain_id)=(/search/, 1861) is duplicated.
discourse=# REINDEX INDEX CONCURRENTLY "pg_toast"."pg_toast_2782645_index_ccnew";
REINDEX
discourse=# REINDEX INDEX CONCURRENTLY "index_incoming_referers_on_path_and_incoming_domain_id_ccnew1";
ERROR:  could not create unique index "index_incoming_referers_on_path_and_incoming_domain_id_c_ccnew1"
DETAIL:  Key (path, incoming_domain_id)=(/search/, 1905) is duplicated.

Ja, bitte lösche die doppelten Zeilen.

@riking Das Korruptieren von Indizes in PostgreSQL ist ein PostgreSQL-Fehler, kein Discourse-Fehler. Wir können zwar die Leistung dieses Einfügevorgangs verbessern, aber der PostgreSQL-Fehler muss in PostgreSQL selbst behoben werden.

Meine Vermutung ist, dass dies mit einer Art unsachgemäßem Herunterfahren der Datenbank-Engine zusammenhängt, möglicherweise aufgrund eines Stromausfalls.

Das ist eine plausible Erklärung. Führt ./launcher shutdown app (oder rebuild) eine saubere Abschaltung von PostgreSQL durch oder auf andere Weise? Oh, aber ich wette, dass ein unbeaufsichtigtes Upgrade nicht weiß, wie man Docker-Container sauber herunterfährt, oder?