Sto scrivendo questo post riguardo a un errore di chunk mancante in una tabella postgres che stava fallendo i miei backup giornalieri. Sono riuscito a risolverlo e voglio esporre il metodo che ho utilizzato nel caso potesse essere utile a qualcun altro che incontra questo problema. Questo non è in alcun modo una guida o istruzioni professionali su come risolvere correttamente gli errori di chunk mancante di postgres perché non sono un esperto e l’ho fatto senza avere molta conoscenza, ma alla fine ha funzionato.
L’errore che stavo ricevendo durante i backup:
pg_dump: error: Dumping the contents of table "stylesheet_cache" failed: PQgetResult() failed.
pg_dump: error: Error message from server: ERROR: missing chunk number 0 for toast value 1903804 in pg_toast_22663
pg_dump: error: The command was: COPY public.stylesheet_cache (id, target, digest, content, created_at, updated_at, theme_id, source_map) TO stdout;
Quindi il problema era nella tabella stylesheet_cache, ERROR: missing chunk number 0 for toast value 1903804 in pg_toast_22663.
Sto usando Discourse in Docker, quindi ecco cosa ho fatto:
ssh into the server
cd /path/to/discourse
./launcher rebuild app
su postgres -c "psql discourse"
Una volta dentro postgres, ho provato a REINDEXARE la tabella sperando che risolvesse il problema.
discourse=# select reltoastrelid::regclass from pg_class where relname = 'stylesheet_cache';
reltoastrelid
-------------------------
pg_toast.pg_toast_18396
(1 row)
REINDEX table stylesheet_cache;
REINDEX table pg_toast.pg_toast_18396;
VACUUM analyze stylesheet_cache;
Ho provato a fare di nuovo il backup, ma è fallito ancora, quindi ho dovuto continuare a cercare la corruzione.
Ho calcolato il numero totale di righe nella mia tabella con:
select count(*) from stylesheet_cache;
Ho ottenuto un conteggio di 2260 righe.
Sono andato a trovare la riga esatta che era corrotta e l’ho cancellata, in qualche modo ho presunto che stylesheet_cache non fosse qualcosa che potesse realmente rompere il mio intero db. Come ho detto, non sono un esperto, quindi forse ho fatto un salto di fede troppo grande, quindi fai attenzione quando lo fai perché potresti incasinare il tuo db.
Ho usato le query LIMIT e OFFSET per trovare le righe corrotte
select * from stylesheet_cache order by id limit 100 offset 0;
Ho giocato con offset e limit finché non ho ottenuto l’errore Missing chunk… e poi ho ristretto a LIMIT 1 e ho spostato la riga che era corrotta. Nel mio caso c’erano 5 righe corrotte.
Potresti usare uno script sh per trovare la riga con meno sforzo, io ho fatto la via manuale che ha richiesto un po’ di tempo, ma potresti usare questo:
#!/bin/sh
j=0
while [ $j -lt 2260 ]
do
psql -U postgres -d discourse -c "SELECT * FROM stylesheet_cache LIMIT 1 offset $j" >/dev/null || echo $j
j=$(($j+1))
done
Sono andato a trovare l’id della riga corrotta con il seguente comando:
select id from stylesheet_cache order by id limit 1 offset 450;
id
----
11498
Quindi l’id della mia riga corrotta era 11498
Ho cancellato la riga con
delete from stylesheet_cache where id = 11498;
Dopo aver cancellato le righe corrotte, sono tornato a REINDEXARE di nuovo
REINDEX table stylesheet_cache;
REINDEX table pg_toast.pg_toast_40948;
VACUUM analyze stylesheet_cache;
E ho provato di nuovo il backup, questa volta ha funzionato. Mi sono guidato usando queste istruzioni di recupero postgres: Postgres error: Missing chunk 0 for toast value in pg_toast · GitHub
DISCLAIMER: questa non è un’opinione di un esperto, quindi procedi con cautela se hai corruzioni simili di chunk mancanti e stai cercando di risolverle.