Aggiorniamo l’immagine Docker di PostgreSQL (magari da 16.0 a 16.11), riavviamo il container e nei log compare questo messaggio:
WARNING: database "main_db" has a collation version mismatch
DETAIL: The database was created using collation version 2.36, but the operating system provides version 2.41.
HINT: Rebuild all objects in this database that use the default collation and run ALTER DATABASE main_db REFRESH COLLATION VERSION, or build PostgreSQL with the right library version.
Panico? No. Ma è un warning che va capito e risolto.
Perché compare questo errore?
Quando usiamo PostgreSQL dentro Docker, il database si appoggia alla libreria di sistema (tipicamente glibc) presente nell’immagine base del container per gestire le collation, cioè le regole di ordinamento e confronto delle stringhe.
Esempio:
- come vengono ordinate le lettere accentate
- se “a” è uguale o diversa da “A”
- come vengono confrontate stringhe in un indice UNIQUE
Quando il database viene creato, PostgreSQL registra la versione della collation disponibile in quel momento (es. 2.36).
Se in seguito aggiorniamo l’immagine Docker, potremmo ottenere una versione diversa della libreria (es. 2.41).
Risultato:
PostgreSQL si accorge che l’ordinamento di sistema potrebbe essere cambiato e mostra il warning di collation version mismatch.
È grave?
No, non è una corruzione del database.
Il database continua a funzionare normalmente. Tuttavia:
Gli indici su colonne
textovarcharpotrebbero essere stati costruiti con regole di ordinamento diverse.Le constraint UNIQUE potrebbero teoricamente comportarsi in modo diverso.
Gli ORDER BY potrebbero restituire risultati leggermente diversi rispetto al passato.
Nella maggior parte dei casi non noteremo alcun problema concreto.
Ma PostgreSQL ci sta dicendo: “Se le regole di ordinamento sono cambiate, è meglio ricostruire gli indici per allinearli alla nuova versione”.
Perché succede spesso in Docker?
Le immagini ufficiali di PostgreSQL si basano su distribuzioni Linux (es. Debian). Quando aggiorniamo l’immagine:
cambia PostgreSQL
può cambiare anche la versione di glibc
quindi cambia la versione delle collation
Anche se il nostro volume dati è lo stesso, l’ambiente runtime non lo è più.
Questo è uno degli effetti collaterali “silenziosi” degli aggiornamenti di immagine nei container.
La soluzione corretta
La soluzione è quella suggerita direttamente dal messaggio di PostgreSQL:
(Consigliato) Eseguiamo un backup
Non è obbligatorio, ma è buona pratica prima di operazioni strutturali:
pg_dump -Fc -d main_db -f main_db_before_reindex.dump
Ricostruiamo gli indici
Opzione standard (con lock):
REINDEX DATABASE main_db;
In produzione è preferibile la versione concorrente:
REINDEX (CONCURRENTLY) DATABASE main_db;
Questa modalità:
- non blocca le query normali
- è più lenta
- è più sicura in ambienti live
Aggiorniamo la versione della collation registrata
Dopo il reindex:
ALTER DATABASE main_db REFRESH COLLATION VERSION;
A questo punto il warning scompare definitivamente.
È un warning che possiamo ignorare?
Tecnicamente possiamo ignorarlo se:
- è un ambiente di sviluppo
- non abbiamo indici su colonne testuali
- non abbiamo constraint UNIQUE su stringhe
In produzione, invece, è consigliato risolverlo per evitare comportamenti inconsistenti nel lungo periodo.