Le migrazioni di Goose per modifiche fluide al database

Ciao, amico!

Oggi parliamo di cosa sono le migrazioni del database e perché sono così importanti. Nel mondo di oggi, non sorprende che qualsiasi cambiamento a un database debba essere fatto con attenzione e secondo un processo specifico. Idealmente, questi passaggi dovrebbero essere integrati nella nostra pipeline CI/CD affinché tutto funzioni automaticamente.

Ecco la nostra agenda:

  1. Qual è il problema?
  2. Come lo risolviamo?
  3. Un esempio semplice
  4. Un esempio più complesso
  5. Raccomandazioni
  6. Risultati
  7. Conclusione

Qual è il problema?

Se il tuo team non ha mai affrontato le migrazioni del database e non sei del tutto sicuro del perché siano necessarie, cerchiamo di chiarirlo. Se conosci già le basi, sentiti libero di saltare.

Principale sfida

Quando apportiamo cambiamenti “programmati” e “graduali” al database, dobbiamo mantenere la disponibilità del servizio e soddisfare i requisiti SLA (affinché gli utenti non subiscano interruzioni o ritardi). Immagina di voler cambiare un tipo di colonna in una tabella con 5 milioni di utenti. Se lo fai “in modo diretto” (ad esempio, eseguendo semplicemente ALTER TABLE senza preparazione), la tabella potrebbe rimanere bloccata per un tempo significativo — e i tuoi utenti rimarrebbero senza servizio.

Per evitare tali mal di testa, segui due regole:

  1. Applica le migrazioni in un modo che non blocchi la tabella (o almeno minimizzi i blocchi).
  2. Se hai bisogno di cambiare un tipo di colonna, è spesso più facile creare prima una nuova colonna con il tipo corretto e poi eliminare quella vecchia.

Un altro problema: Controllo delle versioni e Ripristini

A volte è necessario ripristinare una migrazione.

Farlo manualmente — accedendo al database di produzione e modificando i dati — non è solo rischioso ma anche probabilmente impossibile se non hai accesso diretto. È qui che gli strumenti di migrazione dedicati risultano utili. Ti permettono di applicare le modifiche in modo pulito e di ripristinarle se necessario.

Come lo risolviamo? Usa gli strumenti giusti

Ogni linguaggio ed ecosistema ha i propri strumenti di migrazione:

  • Per Java, Liquibase o Flyway sono comuni.
  • Per Go, una scelta popolare è goose (quello che esamineremo qui).
  • E così via.

Goose: Cos’è e perché è utile

Goose è un’utilità leggera per Go che ti aiuta a gestire le migrazioni automaticamente. Offre:

  • Semplicità. Dipendenze minime e una struttura di file trasparente per le migrazioni.
  • Versatilità. Supporta vari driver DB (PostgreSQL, MySQL, SQLite, ecc.).
  • Flessibilità. Scrivi migrazioni in codice SQL o Go.

Installare Goose

Shell

 

Come Funziona: Struttura di Migrazione

Per impostazione predefinita, Goose cerca i file di migrazione in db/migrations. Ogni migrazione segue questo formato:

Shell

 

  • NNN è il numero di migrazione (ad es., 001, 002, ecc.).
  • Dopo di che, puoi avere un qualsiasi nome descrittivo, ad esempio init_schema.
  • L’estensione può essere .sql o .go.

Esempio di una Migrazione SQL

File: 001_init_schema.sql:

SQL

 

Il nostro Primo Esempio

Cambiare il Tipo di Colonna (Stringa → Intero)

Supponiamo di avere una tabella users con una colonna age di tipo VARCHAR(255). Ora vogliamo cambiarlo in INTEGER. Ecco come potrebbe apparire la migrazione (file 005_change_column_type.sql):

SQL

 

Cosa sta succedendo qui:

  1. Migrazione Up

    • Cambiamo la colonna age in INTEGER. La clausola USING (age::INTEGER) dice a PostgreSQL come convertire i dati esistenti al nuovo tipo.
    • Nota che questa migrazione fallirà se ci sono dati in age che non sono numerici. In tal caso, avrai bisogno di una strategia più complessa (vedi sotto).
  2. Rollback della migrazione

    • Se torniamo indietro, riportiamo età a VARCHAR(255).
    • Utilizziamo di nuovo USING (età::TEXT) per convertire da INTEGER a testo.

Casi Secondari e Complessi: Migrazioni a più passaggi

Se la colonna età potrebbe contenere dati disordinati (non solo numeri), è più sicuro fare questo in diversi passaggi:

  1. Aggiungi una nuova colonna (età_int) di tipo INTEGER.
  2. Copia i dati validi nella nuova colonna, gestendo o rimuovendo le voci non valide.
  3. Elimina la vecchia colonna.
SQL

 

Per consentire un corretto rollback, la sezione Down riflette semplicemente le azioni in ordine inverso.

L’Automazione è Fondamentale

Per risparmiare tempo, è davvero conveniente aggiungere i comandi di migrazione a un Makefile (o a qualsiasi altro sistema di build). Di seguito è riportato un esempio di Makefile con i principali comandi di Goose per PostgreSQL.

Supponiamo:

  • Il DSN per il database è postgres://utente:password@localhost:5432/nomedb?sslmode=disable.
  • I file di migrazione si trovano in db/migrations.
Shell

 

Come usarlo?

1. Crea una nuova migrazione (file SQL). Questo genera un file db/migrations/002_add_orders_table.sql.

Shell

 

2. Applica tutte le migrazioni. Goose creerà una tabella schema_migrations nel tuo database (se non esiste già) e applicherà eventuali nuove migrazioni in ordine crescente.

Shell

 

3. Ritorna all’ultima migrazione. Basta eseguire il rollback dell’ultima migrazione.

Shell

 

4. Ritorna a tutte le migrazioni (usa cautela in produzione). Reset completo.

Shell

 

5. Controlla lo stato delle migrazioni.

Shell

 

Esempio di output:

Shell

 

Riepilogo

Utilizzando gli strumenti di migrazione e un Makefile, possiamo:

  1. Limitare l’accesso diretto al database di produzione, apportando modifiche solo tramite migrazioni.
  2. Tracciare facilmente le versioni del database e tornare indietro in caso di problemi.
  3. Mantenere un’unica, coerente storia delle modifiche al database.
  4. Eseguire migrazioni “fluide” che non interromperanno un ambiente di produzione in esecuzione nel mondo dei microservizi.
  5. Ottenere una validazione extra: ogni modifica passerà attraverso un processo di revisione del codice (supponendo che tu abbia quelle impostazioni attive).

Un altro vantaggio è che è facile integrare tutti questi comandi nel tuo flusso di lavoro CI/CD. E ricorda — la sicurezza prima di tutto. 

Ad esempio:

YAML

 

Conclusione e consigli

Le idee principali sono così semplici:

  • Mantieni le tue migrazioni piccole e frequenti. Sono più facili da rivedere, testare e annullare se necessario.
  • Usa lo stesso strumento in tutti gli ambienti in modo che sviluppo, staging e produzione siano sincronizzati.
  • Integra le migrazioni nel CI/CD così da non dipendere da una sola persona che le esegue manualmente.

In questo modo, avrai un processo affidabile e controllato per cambiare la struttura del tuo database – uno che non interrompe la produzione e ti consente di rispondere rapidamente se qualcosa va storto.

Buona fortuna con le tue migrazioni!

Grazie per aver letto!

Source:
https://dzone.com/articles/goose-as-crucial-tool-for-your-service