Un Blog su SQL Server e dintorni organizzato In Pillole

Database versioning

Uno dei principali problemi nel gestire un database durante lo sviluppo di applicazioni complesse è quello di versionarne lo schema e magari il contenuto di alcune delle tabelle.

Innanzitutto cosa intendiamo per “database versioning”?

Significa principalmente tenere traccia di tutto quello che viene fatto in termini di sviluppo sul nostro DB, come se fosse una qualsiasi codebase di qualsiasi linguaggio; saper gestire in maniera ottimale questo aspetto può toglierci dei bei mal di testa e soprattutto può aiutarci nel rispondere a domande di questo tipo:

  • qual’era il codice della stored procedure X in tal giorno?
  • chi l’ha modificata?
  • chi ha aggiunto il campo Z nella tabella Y?
  • raccogliere tutti gli scripts da rilasciare per un determinato rilascio

Voglio descrivere due approcci che per ora ritengo tra i migliori in base al caso d’uso in cui ci si trova.

Applicazione on premise, molti clienti, tante versioni: migration scripts

Siamo nel caso in cui abbiamo tanti clienti o comunque molte installazioni del nostro prodotto. Difficilmente possiamo prevedere la messa in campo di un compare tra il nostro database di sviluppo e quello di queste molteplici istanze appena citate.

L’approccio che userei in questo caso è la generazione di scripts di migrazione costruiti ad-hoc per la versione che voglio andare ad installare. Quindi ad esempio:

  • per la versione 1: script 1.1, 1.2, 1.3
  • per la versione 2: script 2.1, 2.2, 2.n
  • così via

Il passaggio dalla versione del codice 1 alla n sarà ottenuto dall’esecuzione in primis di tutti gli scripts afferenti la versione di origine, quelle intermedie e la finale.

Come ottenere quest’obiettivo è difficile da descrivere, dipende molto secondo me: dalle tecnologie in uso (stiamo usando un ORM? linguaggio? framework? ecc…), da com’è organizzato il team, ecc…

Possiamo iniziare banalmente con il raccogliere scripts, utilizzare una buona convenzione per il nome file e versionare il tutto attraverso source version control che già utilizziamo nella nostra organizzazione (es. svn, git, …)

Come pattern per un buon nome file valuterei qualcosa del tipo:

[versione_prodotto]_[indice]_[data/ora]_[breve descrizione].sql

  • versione prodotto: dipendenza tra il prodotto e lo script
  • indice: numero progressivo sequenziale
  • data/ora: data ed ora in cui abbiamo creato lo script
  • breve descrizione: cosa contiene lo script a grandi linee? (creazione tabella, aggiunta campi, alter procedure, …)

Quindi ad esempio: 1.0.1_001_20220402H1014_Creazione tabella X.sql

Sfruttando invece un ORM come ad esempio Entity Framework la funzionalità delle database migrations è praticamente built in nel framework stesso (vedi link).

Il vantaggio principale di un approccio di questo tipo è la forte flessibilità che diamo al nostro prodotto; se siamo bravi a gestire bene i nostri script ad esempio corredandoli anche di una parte di rollback (in genere cosa molto complessa), potremmo essere in grado anche di muoverci da una versione ad un’altra tornando anche indietro (magari per questioni di test).

Applicazione mono cliente o mono installazione: database compare

Supponiamo di dover invece installare il database una sola volta e tenerlo aggiornato da una nostra “sorgente” alla destinazione.

Questo scenario a mio avviso si sposa molto bene con i progetti Database messi a disposizione da Visual Studio (vedete sotto uno screen).

Nuovo progetto database.

Questo tipo di progetti mette a disposizione la fantastica possibilità di effettuare uno schema compare e data compare, il tutto direttamente da Visual Studio.

Confronto database da Visual Studio.

Lo screen mostra il confronto fatto tra un database sul mio SQLEXPRESS vs i files di progetto sul mio pc. Posso eventualmente anche:

  • confrontare istanze di database tra loro
  • aggiornare direttamente database o il progetto DB
  • se non sono certo dell’effetto di quest’operazione posso generare prima uno script di aggiornamento
  • pubblicare il progetto DB per generare una nuova istanza pulita e pronta all’uso

Insomma le funzionalità sono molteplici e vanno approfondite direttamente sul prodotto.

Il progetto DB non fa altro che salvare tutta la struttura ed eventualmente i dati in files di script (organizzanti nel nostro progetto) che poi chiaramente versioneremo con il nostro git.

Conclusioni

Spero che quest’articolo sia stato in grado di fornire degli spunti iniziali per poter gestire l’annoso problema del versionamento database.

Chiaramente non vuole essere una soluzione definitiva, manca di molte parti che vanno assolutamente definite ed approfondite.

Inoltre ho provato ad identificare due approcci che potessero essere categorizzati in base al numero di installazioni da effettuare; non è assolutamente detto che non si trovi utile un primo approccio con la mono-installazione o il secondo con clienti multipli.

L’unica soluzione credo sia quella di sperimentare e con l’esperienza sul proprio prodotto scegliere poi la strada più efficiente.

Sarei curioso di conoscere quali strategie adottate per i vostri progetti.

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *