Aggiornamento 2.7.0.beta2 fallito con ERRORE: chiave duplicata

Stavo aggiornando dalla versione 2.7.0.beta1 e ho ricevuto questo messaggio di errore:

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: Si è verificato un errore, questa e tutte le successive migrazioni sono state annullate:

PG::UniqueViolation: ERRORE: valore di chiave duplicato viola il vincolo univoco "index_users_on_username"
DETTAGLIO:  La chiave (username)=(DaveW) esiste già.

E poi, alla fine dell’output:

I, [2021-01-22T20:16:42.805286 #1] INFO -- : Terminazione dei processi asincroni

I, [2021-01-22T20:16:42.805333 #1] INFO -- : Invio di INT a 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 -- : Invio di TERM a exec chpst -u redis -U redis /usr/bin/redis-server /etc/redis/redis.conf pid: 166

166:signal-handler (1611346602) Ricevuto SIGTERM, programmazione di arresto...

2021-01-22 20:16:42.805 UTC [49] LOG: richiesta di arresto rapido ricevuta

2021-01-22 20:16:42.835 UTC [49] LOG: annullamento di tutte le transazioni attive

2021-01-22 20:16:42.857 UTC [49] LOG: il worker in background "logical replication launcher" (PID 58) è uscito con codice di uscita 1

166:M 22 Jan 2021 20:16:42.876 # Arresto richiesto dall'utente...

166:M 22 Jan 2021 20:16:42.876 * Salvataggio dell'ultimo snapshot RDB prima dell'uscita.

166:M 22 Jan 2021 20:16:44.758 * DB salvato su disco

166:M 22 Jan 2021 20:16:44.758 # Redis è ora pronto per uscire, arrivederci...

2021-01-22 20:16:45.563 UTC [53] LOG: arresto in corso

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 non si è arrestato correttamente, forzatura dell'arresto!

FALLITO

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

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

Posizione dell'errore: /pups/lib/pups/exec_command.rb:112:in `spawn'

exec fallito con i parametri {"cd"=>"$home", "hook"=>"db_migrate", "cmd"=>["su discourse -c 'bundle exec rake db:migrate'"]}

d627ad17d1f22d839a7dc8099878e6272eb3ea1772539f6628e2a23dd830aca2

** FALLITO L'AVVIO ** scorri verso l'alto e cerca altri messaggi di errore precedenti, potrebbero essercene più di uno.

./discourse-doctor può aiutare a diagnosticare il problema.

Non ho idea di come possano esserci due account con lo stesso nome utente.

Il nostro sito è completamente down. Cosa devo fare ora?

Grazie,
Gunnar

2 Mi Piace

Credo che tu possa riavviare il sito con ./launcher start app

Quindi dai un’occhiata ai modi per eliminare il duplicato:

e

5 Mi Piace

Altre informazioni che dovrei probabilmente fornire:

  • Si tratta di un’installazione con un singolo contenitore.
  • Il primo rebuild è stato completato senza errori. Questo errore si è verificato mentre eseguivo il secondo rebuild, dopo che il primo era stato completato con successo.

Grazie,
Gunnar

1 Mi Piace

Hai abbastanza spazio su disco? Errore relativo all’aggiornamento richiesto di PostgreSQL alla versione 13, per quanto ne so. Hai seguito questo metodo di aggiornamento?

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

Se cerchi nel forum quei errori, vedrai molte informazioni passate e possibili soluzioni.

Prova questo.

Cerca nel forum gli errori che hai pubblicato per vedere le varie soluzioni che hanno funzionato per altri.

1 Mi Piace

Ho riportato il sito online rinominando postgres_data_old in postgres_data e poi eseguendo ./launcher start app per avviare la vecchia immagine.

Quindi, sono tornato al punto di partenza, ma almeno il sito è online.

Ho cercato di trovare la chiave duplicata eseguendo questo comando:

select * from users WHERE username = 'DaveW';

(username = DaveW era la chiave problematica, come mostrato nel messaggio di errore nel mio primo post in questa discussione.)

Il comando ha restituito una sola riga, un solo utente. Cosa sto trascurando?

Grazie,
Gunnar

1 Mi Piace

Ne hai due, forse con maiuscole diverse nel DB:

1 Mi Piace

Hai visitato il mio sito? :wink:

Capisco cosa intendi: quando cerco nell’interfaccia grafica, vedo effettivamente due account. Tuttavia, quando faccio clic su entrambi come amministratore e apro la pagina dei dettagli, sembrano essere lo stesso utente. Non riesco a trovare un singolo dettaglio diverso tra i due. In pratica, indipendentemente da quale dei due clicco, ottengo i dati del secondo, quello con il nome completo inserito.

Poiché quell’utente non aveva mai pubblicato ed era inattivo da un po’, ho eliminato l’account dall’interfaccia grafica.

Curiosamente, mi rimane l’altro, il primo della tua lista, senza nome completo. Ma ora, se provo a cliccare su quell’utente, non succede nulla. Vedo apparire una finestra di dialogo che tenta di aprirsi, per poi chiudersi immediatamente.

Cercando direttamente nel database per username = DaveW ora restituisce zero righe. Tuttavia, se cerco con

select * from users WHERE name = 'DaveW';

(name, non username,) ottengo una riga restituita:

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

Notate come nel campo username ci sia DaveW (stessa grafia)! Questo account è anche tre anni più vecchio dell’altro.

Posso eliminarlo con:

DELETE from users WHERE id = 19732;

senza alcun effetto negativo?

Grazie per tutto il vostro aiuto!

Gunnar

1 Mi Piace

Certo! :grinning:

Questo dovrebbe eliminare il 19732, ma non posso garantire l’assenza di eventuali effetti collaterali. In ogni caso, è consigliabile eseguire un backup prima di procedere ulteriormente.

3 Mi Piace

Potresti anche modificare il nome utente di uno dei duplicati.

2 Mi Piace

Giusto.

Una volta fatto, dovrei essere in grado di ricominciare l’aggiornamento da capo? Cioè, eseguire rebuild due volte?

Grazie!
Gunnar

4 Mi Piace

Dovrebbe funzionare. A meno che non ci siano altri utenti duplicati.

2 Mi Piace

Risulta che ce ne sono, almeno uno.

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

C’è un modo per scansionare il database alla ricerca di duplicati? Non solo utenti, ma qualsiasi tabella che potrebbe causare questo errore durante l’aggiornamento?

Vorrei individuarli e risolverli tutti prima di riprovare.

Inoltre, sarebbe utile che questo facesse parte del processo di aggiornamento. Forse eseguire prima una scansione e interrompere il processo prima di apportare modifiche. Avvisare l’utente e fornire un elenco dei duplicati, con un link a una pagina qui su meta con le istruzioni su come risolvere?

2 Mi Piace

Un approccio meno invasivo potrebbe essere quello di reindicizzare il database prima dell’aggiornamento; questo dovrebbe indicarti quali devono essere corretti.

2 Mi Piace

Non sono un esperto di database, quindi questa cosa mi sembra spaventosa. E se ho capito bene, alla fine ti ritrovi con indici duplicati che devi eliminare manualmente?

Inoltre, ecco la parte strana. Come hai notato sul mio sito con il duplicato precedente, ora ho trovato un utente duplicato, RobS, nell’interfaccia grafica. Ma, proprio come prima, non importa quale dei due clicchi, finisci sempre sulla pagina del profilo di uno solo di loro. Cioè:

  • Elenca gli utenti chiamati RobS nell’interfaccia grafica. Trovane due. Nota che entrambi hanno statistiche diverse.
  • Clicca sull’utente #1. Vedi il profilo e le statistiche che appartengono all’utente #2.
  • Clicca sull’utente #2. Vedi il profilo e le statistiche che appartengono all’utente #2.

select * from users WHERE username_lower = 'robs';

Restituisce 1 riga: quella che sembra essere l’utente #2 (le date corrispondono).

select * from users WHERE username = 'RobS';

Restituisce anch’esso solo 1 riga: quella che sembra essere l’utente #1 (anche qui, le date corrispondono). Questo utente ha un ID diverso dall’altro.

A giudicare dall’output, entrambi avevano lo stesso username e username_lower, eppure ogni istruzione SELECT restituiva solo 1 riga. Il mio database è in gravi difficoltà?

Una reindicizzazione risolverebbe il problema?

2 Mi Piace

Ho provato a ricostruire di nuovo e ho trovato un altro duplicato con il nome utente “drc”. Nell’interfaccia grafica, ho individuato questi due:

Deborah C
David C

Prova a fare clic su uno dei due utenti per vedere i dettagli nella loro “scheda” del profilo. Noterai che, indipendentemente da quale dei due clicchi, verranno visualizzati i dettagli di Deborah C.

Non ho idea di come sia successo, ma qual è la migliore strategia da adottare ora? Ho rinunciato all’aggiornamento finché non riesco a superare questo problema.

Come potrei reindicizzare? In questo modo?

REINDEX SCHEMA CONCURRENTLY public;

Questo mi indicherebbe quali chiavi sono duplicate?

1 Mi Piace

Mi chiedo cosa restituirebbe quanto segue:

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

Non sarà una cosa banale come un entry del nome utente con spazi bianchi, o un carattere non stampabile / unicode in qualche modo all’interno?

1 Mi Piace

Credo di sì, anche se non so se esista un modo migliore per farlo. Sulla mia istanza di test viene eseguito senza produrre alcun output. Quando ho aggiornato il mio sito in produzione, c’era solo una chiave duplicata da gestire, quindi la mia esperienza potrebbe non essere un buon esempio per la tua situazione. In ogni caso, fai un backup prima delle operazioni sul database: di solito creo uno snapshot su DigitalOcean, così in caso di problemi il ripristino è rapido e semplice.

1 Mi Piace

Penso che sia così che ho risolto casi simili in passato. Ricrea l’indice; quando fallisce, ti indicherà l’elemento duplicato. Correggilo, poi riprova. Ripeti.

2 Mi Piace

Grazie. Quando fallisce, come faccio a trovare ed eliminare il nuovo indice incompleto? È semplice come aggiungere “_ccnew” al nome della tabella che ha fallito?

Cioè, quando si blocca su “users” a causa di un duplicato, devo prima correggere il duplicato, poi:

DROP index ‘users_ccnew’;

Poi ricominciare e ripetere? È così semplice?

Grazie,
Gunnar

1 Mi Piace

Ah, sì. Mi trovo nella situazione di aver trovato due utenti validi (e attivi) con lo stesso username e username_lower:

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

Sembra che debba modificare sia l’username che l’username_lower del secondo utente. Come posso farlo in psql?

Grazie!
Gunnar

1 Mi Piace