Upgrade 2.7.0.beta2 fehlgeschlagen mit FEHLER: doppelter Schlüssel

Ich habe ein Upgrade von 2.7.0.beta1 durchgeführt und diese Fehlermeldung erhalten:

2021-01-22 20:16:22.015 UTC [4055] discourse@discourse LOG:  duration: 75335.241 ms  statement: UPDATE notifications SET processed = true
2021-01-22 20:16:23.792 UTC [4055] discourse@discourse LOG:  duration: 1776.591 ms  statement: ALTER TABLE "notifications" ALTER COLUMN "processed" SET NOT NULL
2021-01-22 20:16:25.198 UTC [4055] discourse@discourse LOG:  duration: 1323.298 ms  statement: CREATE  INDEX  "index_notifications_on_processed" ON "notifications"  ("processed")
2021-01-22 20:16:25.458 UTC [4055] discourse@discourse LOG:  duration: 241.063 ms  statement: CREATE TABLE "user_notification_schedules" ("id" bigserial primary key, "user_id" integer NOT NULL, "enabled" boolean DEFAULT FALSE NOT NULL, "day_0_start_time" integer NOT NULL, "day_0_end_time" integer NOT NULL, "day_1_start_time" integer NOT NULL, "day_1_end_time" integer NOT NULL, "day_2_start_time" integer NOT NULL, "day_2_end_time" integer NOT NULL, "day_3_start_time" integer NOT NULL, "day_3_end_time" integer NOT NULL, "day_4_start_time" integer NOT NULL, "day_4_end_time" integer NOT NULL, "day_5_start_time" integer NOT NULL, "day_5_end_time" integer NOT NULL, "day_6_start_time" integer NOT NULL, "day_6_end_time" integer NOT NULL)
2021-01-22 20:16:25.560 UTC [4055] discourse@discourse LOG:  duration: 100.868 ms  statement: CREATE  INDEX  "index_user_notification_schedules_on_user_id" ON "user_notification_schedules"  ("user_id")
2021-01-22 20:16:25.782 UTC [4055] discourse@discourse LOG:  duration: 142.180 ms  statement: CREATE  INDEX  "index_do_not_disturb_timings_on_scheduled" ON "do_not_disturb_timings"  ("scheduled")
2021-01-22 20:16:26.414 UTC [4055] discourse@discourse LOG:  duration: 361.514 ms  statement: UPDATE users
	SET locale = 'en_GB'
	WHERE locale = 'en'
	
2021-01-22 20:16:26.656 UTC [4055] discourse@discourse LOG:  duration: 132.778 ms  statement: UPDATE theme_translation_overrides
	SET locale = 'en_GB'
	WHERE locale = 'en'
	
2021-01-22 20:16:42.745 UTC [4055] discourse@discourse ERROR:  duplicate key value violates unique constraint "index_users_on_username"
2021-01-22 20:16:42.745 UTC [4055] discourse@discourse DETAIL:  Key (username)=(DaveW) already exists.
2021-01-22 20:16:42.745 UTC [4055] discourse@discourse STATEMENT:  UPDATE users
	SET locale = 'en'
	WHERE locale = 'en_US'
	
rake aborted!
StandardError: An error has occurred, this and all later migrations canceled:

PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_users_on_username"
DETAIL:  Key (username)=(DaveW) already exists.

Und am Ende der Ausgabe:

I, [2021-01-22T20:16:42.805286 #1] INFO -- : Terminating async processes

I, [2021-01-22T20:16:42.805333 #1] INFO -- : Sending INT to HOME=/var/lib/postgresql USER=postgres exec chpst -u postgres:postgres:ssl-cert -U postgres:postgres:ssl-cert /usr/lib/postgresql/13/bin/postmaster -D /etc/postgresql/13/main pid: 49

I, [2021-01-22T20:16:42.805381 #1] INFO -- : Sending TERM to exec chpst -u redis -U redis /usr/bin/redis-server /etc/redis/redis.conf pid: 166

166:signal-handler (1611346602) Received SIGTERM scheduling shutdown...

2021-01-22 20:16:42.805 UTC [49] LOG: received fast shutdown request

2021-01-22 20:16:42.835 UTC [49] LOG: aborting any active transactions

2021-01-22 20:16:42.857 UTC [49] LOG: background worker "logical replication launcher" (PID 58) exited with exit code 1

166:M 22 Jan 2021 20:16:42.876 # User requested shutdown...

166:M 22 Jan 2021 20:16:42.876 * Saving the final RDB snapshot before exiting.

166:M 22 Jan 2021 20:16:44.758 * DB saved on disk

166:M 22 Jan 2021 20:16:44.758 # Redis is now ready to exit, bye bye...

2021-01-22 20:16:45.563 UTC [53] LOG: shutting down

I, [2021-01-22T20:16:52.806177 #1] INFO -- : HOME=/var/lib/postgresql USER=postgres exec chpst -u postgres:postgres:ssl-cert -U postgres:postgres:ssl-cert /usr/lib/postgresql/13/bin/postmaster -D /etc/postgresql/13/main pid:49 did not terminate cleanly, forcing termination!

FAILED

--------------------

Pups::ExecError: cd /var/www/discourse && su discourse -c 'bundle exec rake db:migrate' failed with return #<Process::Status: pid 4032 exit 1>

Location of failure: /pups/lib/pups/exec_command.rb:112:in `spawn'

exec failed with the params {"cd"=>"$home", "hook"=>"db_migrate", "cmd"=>["su discourse -c 'bundle exec rake db:migrate'"]}

d627ad17d1f22d839a7dc8099878e6272eb3ea1772539f6628e2a23dd830aca2

** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one.

./discourse-doctor may help diagnose the problem.

Ich habe keine Ahnung, wie es zwei Konten mit demselben Benutzernamen geben kann.

Unsere Seite ist komplett ausgefallen. Was soll ich jetzt tun?

Vielen Dank,
Gunnar

2 „Gefällt mir“

Ich denke, Sie können die Site mit ./launcher start app wieder hochfahren.

Schauen Sie sich dann Möglichkeiten an, um das Duplikat zu löschen:

und

5 „Gefällt mir“

Weitere Informationen, die ich wahrscheinlich liefern sollte:

  • Dies ist eine Installation mit einem einzelnen Container.
  • Der erste Neuaufbau wurde ohne Fehler abgeschlossen. Dieser Fehler trat auf, als ich den zweiten Neuaufbau ausführte, nachdem der erste Neuaufbau erfolgreich abgeschlossen war.

Vielen Dank,
Gunnar

1 „Gefällt mir“

Hast du genügend Festplattenspeicher? Fehler im Zusammenhang mit dem erforderlichen PostgreSQL-Update auf Version 13, soweit ich weiß. Hast du diese Upgrade-Methode befolgt?

cd /var/discourse
git pull
 ./launcher rebuild app

Wenn du im Forum nach diesen Fehlern suchst, wirst du viele frühere Informationen und mögliche Lösungen finden.

Versuche es damit.

Suche im Forum nach deinen gemeldeten Fehlern, um verschiedene Lösungen zu sehen, die bei anderen funktioniert haben.

1 „Gefällt mir“

Ich habe die Site wieder hochgefahren, indem ich postgres_data_old wieder in postgres_data umbenannt und dann ./launcher start app ausgeführt habe, um das alte Image zu starten.

Also bin ich wieder bei Null, aber zumindest ist die Site wieder online.

Ich habe versucht, den doppelten Schlüssel zu finden, indem ich dies eingegeben habe:

select * from users WHERE username = 'DaveW';

(username = DaveW war der problematische Schlüssel, wie in der Fehlermeldung in meinem ersten Beitrag in diesem Thread gezeigt.)

Der Befehl hat nur eine Zeile, einen Benutzer, zurückgegeben. Was übersehe ich?

Danke,
Gunnar

1 „Gefällt mir“

Sie haben zwei, möglicherweise mit unterschiedlicher Groß- und Kleinschreibung in der Datenbank:

1 „Gefällt mir“

Hast du meine Seite besucht? :wink:

Ich verstehe, was du meinst. Wenn ich in der GUI suche, sehe ich tatsächlich zwei. Wenn ich jedoch als Administrator auf beide klicke und die Detailseite öffne, scheinen es dieselben Benutzer zu sein. Ich kann keinen einzigen Unterschied zwischen den beiden finden. Grundsätzlich erhalte ich, egal auf welchen der beiden ich klicke, die Daten für den zweiten, den mit dem vollständigen Namen.

Da dieser Benutzer niemals gepostet hatte und schon eine Weile nicht mehr aktiv war, habe ich das Konto über die GUI gelöscht.

Interessanterweise habe ich immer noch den anderen, den ersten auf deiner Liste, ohne vollständigen Namen. Aber wenn ich jetzt auf diesen Benutzer klicke, passiert nichts. Ich sehe zwar, dass sich ein Dialog zu öffnen versucht, schließt sich aber sofort wieder.

Eine direkte Suche in der Datenbank nach username = DaveW ergibt jetzt keine Zeilen mehr. Wenn ich jedoch nach

select * from users WHERE name = 'DaveW';

suche (name, nicht username), erhalte ich eine Zeile zurück:

 19732 | DaveW    | 2016-11-15 12:43:02.708166 | 2016-11-15 12:43:02.708166 | DaveW |                    0 |                |               |      | t      | davew          | 2016-11-15 12:43:02.708166 | f     | 2017-06-01 18:09:45.018058 |           1 | f        |                |             |                   |              |                |               |     0 |          0 |            | f         |       |                    |        |                  |                         | f      |               |               |                          |                           | 
(1 Zeile)

Beachte, dass im Feld username ebenfalls DaveW (gleiche Schreibweise) steht! Dieses Konto ist auch drei Jahre älter als das andere.

Kann ich es mit folgendem Befehl entfernen:

DELETE from users WHERE id = 19732;

ohne negative Auswirkungen?

Danke für deine ganze Hilfe!

Gunnar

1 „Gefällt mir“

Natürlich! :grinning:

Das sollte die 19732 löschen, aber ich kann das Fehlen unerwünschter Nebenwirkungen nicht garantieren. Auf jeden Fall ist eine Sicherungskopie vor dem weiteren Vorgehen ratsam.

3 „Gefällt mir“

Sie können auch den Benutzernamen eines der Duplikate ändern.

2 „Gefällt mir“

Richtig.

Sollte ich nach dem Ändern den Upgrade-Vorgang komplett von vorne starten können? Also den Rebuild zweimal ausführen?

Danke!
Gunnar

4 „Gefällt mir“

Das sollte funktionieren. Es sei denn, es gibt weitere doppelte Benutzer.

2 „Gefällt mir“

Es stellt sich heraus, dass es mindestens einen gibt.

PG::UniqueViolation: ERROR:  duplicate key value violates unique constraint "index_users_on_username_lower"
DETAIL:  Key (username_lower)=(robs) already exists.

Gibt es eine Möglichkeit, die Datenbank nach Duplikaten zu durchsuchen? Nicht nur Benutzer, sondern auch jede andere Tabelle, die diesen Fehler während des Upgrades verursachen könnte?

Ich möchte sie finden und alle beheben, bevor ich es erneut versuche.

Außerdem wäre es gut, wenn dies Teil des Upgrade-Prozesses sein könnte. Vielleicht zuerst einen Scan durchführen und den Prozess stoppen, bevor Änderungen vorgenommen werden. Den Benutzer warnen und eine Liste der Duplikate bereitstellen, mit einem Link zu einer Seite hier auf Meta mit Anweisungen zur Behebung?

2 „Gefällt mir“

Ein weniger invasiver Ansatz könnte darin bestehen, die Datenbank vor dem Upgrade neu zu indizieren. Das sollte dir anzeigen, welche Indizes repariert werden müssen.

2 „Gefällt mir“

Ich bin kein Datenbankexperte, daher sieht das beängstigend aus. Und wenn ich das richtig verstehe, führt das dann zu doppelten Indizes, die man manuell löschen muss?

Außerdem ist hier der seltsame Teil. Genau wie du bei meiner Seite mit dem vorherigen Duplikat festgestellt hast, habe ich jetzt in der GUI einen doppelten Benutzer RobS gefunden. Aber genau wie zuvor lande ich, egal auf welchen ich klicke, auf der Profilseite nur eines von ihnen. Also:

  • Benutzer mit dem Namen RobS in der GUI auflisten. Zwei finden. Feststellen, dass beide unterschiedliche Statistiken haben.
  • Benutzer #1 anklicken. Profil und Statistiken von Benutzer #2 anzeigen.
  • Benutzer #2 anklicken. Profil und Statistiken von Benutzer #2 anzeigen.

select * from users WHERE username_lower = 'robs';

Liefert 1 Zeile: Das sieht nach Benutzer #2 aus (die Daten stimmen überein).

select * from users WHERE username = 'RobS';

Liefert ebenfalls nur 1 Zeile: Das sieht nach Benutzer #1 aus (wiederum stimmen die Daten überein). Dieser Benutzer hat eine andere ID als der andere.

Gemessen an der Ausgabe hatten beide denselben username und username_lower, doch jede SELECT-Anweisung lieferte nur 1 Zeile. Ist meine Datenbank in ernsthaften Schwierigkeiten?

Würde eine Neuindizierung das beheben?

2 „Gefällt mir“

Ich habe erneut einen Neuaufbau versucht und dabei noch einen weiteren Duplikat mit dem Benutzernamen „drc

1 „Gefällt mir“

Ich frage mich, was Folgendes zurückgeben würde:

select id, username FROM users WHERE username_lower = 'robs' OR username = 'RobS':

Ist es etwas Dämliches, wie etwa, dass einer der Benutzernamen-Einträge Leerzeichen oder ein nicht druckbares Zeichen / Unicode irgendwie enthält?

1 „Gefällt mir“

Ich denke ja, und ich weiß nicht, ob es einen besseren Weg gibt, dies zu tun. Auf meiner Test-Instanz läuft es einfach ohne Ausgabe. Als ich meine Produktionsseite aktualisiert habe, gab es nur ein Duplikat, mit dem ich mich auseinandersetzen musste, daher ist meine Erfahrung möglicherweise kein gutes Beispiel für deine Situation. In jedem Fall ein Backup vor Datenbankoperationen – ich erstelle normalerweise einen Snapshot bei DigitalOcean, damit die Wiederherstellung im Notfall schnell und einfach wäre.

1 „Gefällt mir“

Ich glaube, so habe ich früher Ähnliches gelöst. Den Index neu aufbauen, wenn er fehlschlägt, wird dir das Duplikat anzeigen, dann behebst du es und versuchst es erneut. Wiederhole das.

2 „Gefällt mir“

Danke. Wenn er fehlschlägt, wie finde und entferne ich den unvollständigen neuen Index? Ist es so einfach, dem Namen der fehlgeschlagenen Tabelle „_ccnew

1 „Gefällt mir“

Ah, ja. Ich befinde mich nun in der Situation, dass ich zwei gültige (und aktive) Benutzer mit demselben Benutzernamen und derselben username_lower gefunden habe:

  id   | username | (redacted) | username_lower |
 42379 | DrC      | (redacted) | drc            |
 47695 | DRC      | (redacted) | drc            |

Anscheinend muss ich sowohl den Benutzernamen als auch die username_lower des zweiten Benutzers ändern. Wie würde ich das in psql machen?

Danke!
Gunnar

1 „Gefällt mir“