Come eseguire in sicurezza le migrazioni di database con più istanze di app?

8

Abbiamo un'applicazione che presenta un mix di migrazioni di database veloci (< 1 secondo) e lente (> 30 secondi). Al momento, stiamo eseguendo le migrazioni dei database come parte dell'elemento della configurazione, ma in seguito lo strumento CI deve conoscere tutte le stringhe di connessione del database per la nostra app (in più ambienti) che non è l'ideale. Vogliamo modificare questo processo in modo che l'applicazione esegua le proprie migrazioni del database all'avvio.

Ecco la situazione:

Abbiamo più istanze di questa applicazione - circa 5 in produzione. Chiamiamoli node1, ..., node5 . Ogni app si connette a una singola istanza di SQL Server e non utilizziamo distribuzioni a rotazione (tutte le app vengono distribuite simultaneamente per quanto ne so)

Problema: diciamo che abbiamo una migrazione a lungo termine. In questo caso, viene avviato node1 , quindi inizia l'esecuzione della migrazione. Ora, node4 viene avviato e la migrazione di lunga durata non è ancora terminata, quindi node4 inizia anche a eseguire la migrazione - > possibile corruzione dei dati? Come eviterai questo problema o il problema è abbastanza importante da preoccupare?

Stavo pensando di risolvere questo problema con un blocco distribuito (usando etcd o qualcosa del genere). Fondamentalmente, tutte le app cercano di acquisire il blocco, solo uno di loro lo ottiene ed esegue le migrazioni, quindi si sblocca. Quando il resto delle app si avvia e entra nella sezione critica, tutte le migrazioni sono già state eseguite in modo che lo script di migrazione sia appena terminato.

Tuttavia, il mio istinto sta dicendo "questo è eccessivo, deve esserci una soluzione più semplice", quindi ho pensato di chiedere qui per vedere se qualcun altro ha qualche idea migliore.

    
posta Ben 23.12.2017 - 21:22
fonte

2 risposte

4

Dato che hai citato il server SQL: secondo questo precedente post DBA.SE , i cambiamenti dello schema possono (e dovrebbero ) essere messo in transazioni. Questo ti dà la possibilità di progettare le tue migrazioni proprio come qualsiasi altra forma di scrittura concorrente sul tuo DB - si avvia una transazione e, quando fallisce, si esegue il rollback. Ciò impedisce almeno alcuni dei peggiori scenari di danneggiamento del database (anche se le transazioni da sole non impediranno la perdita di dati in caso di passaggi di migrazione distruttivi come l'eliminazione di una colonna o tabella).

Finora, sono sicuro che avrai bisogno anche di una tabella migrations dove sono state registrate le migrazioni già applicate, quindi un processo di applicazione può controllare se una migrazione specifica è già stata applicata o meno. Quindi utilizzare "SELEZIONA PER AGGIORNAMENTO" per implementare le migrazioni come questa (pseudo codice):

  • Avvia una transazione
  • SELECT FROM Migrations FOR UPDATE WHERE MigrationLabel='MyMigration42'
  • se la precedente dichiarazione restituisce un valore, termina la transazione
  • applica la migrazione (rollback se fallisce, registra l'errore e termina la transazione)
  • INSERT 'MyMigration42' INTO Migrations(MigrationLabel)
  • termina la transazione

Che crea il meccanismo di blocco direttamente nel "è stato il test di migrazione già applicato" .

Si noti che questa progettazione consentirà, in teoria, di lasciare che i passaggi della migrazione non siano a conoscenza dell'applicazione effettivamente applicata: può essere possibile che il passaggio 1 venga applicato da app1, passaggio 2 da app2, passaggio 3 da app 3, passaggio 4 di app1 di nuovo, e così via. Tuttavia, è anche una buona idea non applicare le migrazioni finché sono in uso altre istanze dell'app. La distribuzione parallela, come menzionato nella domanda, potrebbe già interessare questo vincolo.

    
risposta data 24.12.2017 - 13:14
fonte
0

Forse puoi trovare una libreria che supporta la migrazione del database con più nodi.

Conosco due librerie nel mondo Java, entrambe supportano ciò di cui hai bisogno:

  • Liquibase : dal loro FAQ : Liquibase utilizza un sistema di blocco distribuito per consentire solo a un processo di aggiornare il database alla volta . Gli altri processi attenderanno semplicemente fino al rilascio del blocco.
  • Flyway : dalla loro pagina di download : Sicuro per più nodi in parallelo ✓

Ci sono probabilmente anche altri strumenti per Java e altre lingue.

Se non puoi (o non vuoi) utilizzare tale strumento, una tabella può essere utilizzata come blocco o anche come registro di migrazione, vedi Risposta di Browns del documento per un esempio.

    
risposta data 29.12.2017 - 22:23
fonte

Leggi altre domande sui tag