Domanda

Quali sono i metodi migliori per monitorare e/o automatizzare le modifiche dello schema DB?Il nostro team utilizza Subversion per il controllo della versione e siamo stati in grado di automatizzare alcune delle nostre attività in questo modo (inviando build a un server di staging, distribuendo codice testato a un server di produzione) ma stiamo ancora eseguendo manualmente gli aggiornamenti del database.Mi piacerebbe trovare o creare una soluzione che ci permetta di lavorare in modo efficiente su server con ambienti diversi continuando a utilizzare Subversion come backend attraverso il quale il codice e gli aggiornamenti DB vengono inviati a vari server.

Molti pacchetti software popolari includono script di aggiornamento automatico che rilevano la versione del DB e applicano le modifiche necessarie.È questo il modo migliore per farlo anche su scala più ampia (su più progetti e talvolta su più ambienti e linguaggi)?In tal caso, esiste del codice esistente che semplifica il processo o è meglio semplicemente implementare la nostra soluzione?Qualcuno ha già implementato qualcosa di simile e lo ha integrato negli hook post-commit di Subversion, o è una cattiva idea?

Anche se sarebbe preferibile una soluzione che supporti più piattaforme, abbiamo sicuramente bisogno di supportare lo stack Linux/Apache/MySQL/PHP poiché la maggior parte del nostro lavoro si svolge su quella piattaforma.

È stato utile?

Soluzione

Nel mondo Rails, esiste il concetto di migrazioni, script in cui le modifiche al database vengono apportate in Ruby anziché in un sapore SQL specifico per il database.Il tuo codice di migrazione Ruby finisce per essere convertito nel DDL specifico per il tuo database attuale;questo rende molto semplice il passaggio da una piattaforma di database all'altra.

Per ogni modifica apportata al database, scrivi una nuova migrazione.Le migrazioni in genere hanno due metodi:un metodo "su" in cui vengono applicate le modifiche e un metodo "giù" in cui le modifiche vengono annullate.Un singolo comando aggiorna il database e può anche essere utilizzato per portare il database a una versione specifica dello schema.In Rails, le migrazioni vengono mantenute nella propria directory nella directory del progetto e vengono archiviate nel controllo della versione proprio come qualsiasi altro codice di progetto.

Questa guida Oracle alle migrazioni Rails copre abbastanza bene le migrazioni.

Gli sviluppatori che utilizzano altre lingue hanno esaminato le migrazioni e hanno implementato le proprie versioni specifiche della lingua.So di Ruck, un sistema di migrazioni PHP modellato sulle migrazioni di Rails;potrebbe essere quello che stai cercando.

Altri suggerimenti

Usiamo qualcosa di simile a bcwoord per mantenere gli schemi del nostro database sincronizzati su 5 diverse installazioni (produzione, staging e alcune installazioni di sviluppo) e sottoposti a backup nel controllo della versione, e funziona abbastanza bene.Elaborerò un po':


Per sincronizzare la struttura del database, abbiamo un unico script, update.php, e una serie di file numerati 1.sql, 2.sql, 3.sql, ecc.Lo script utilizza una tabella aggiuntiva per archiviare il numero di versione corrente del database.I file N.sql sono realizzati manualmente, per passare dalla versione (N-1) alla versione N del database.

Possono essere utilizzati per aggiungere tabelle, aggiungere colonne, migrare i dati da un formato di colonna vecchio a uno nuovo, quindi eliminare la colonna, inserire righe di dati "principali" come i tipi di utente, ecc.Fondamentalmente, può fare qualsiasi cosa e con gli script di migrazione dei dati adeguati non perderai mai i dati.

Lo script di aggiornamento funziona in questo modo:

  • Connettersi al database.
  • Effettua un backup del database corrente (perché stuff Volere andare storto) [mysqldump].
  • Crea una tabella contabile (chiamata _meta) se non esiste.
  • Leggi la VERSIONE corrente dalla tabella _meta.Assumere 0 se non trovato.
  • Per tutti i file .sql con numero superiore a VERSION, eseguirli in ordine
  • Se uno dei file ha prodotto un errore:ripristinare il backup
  • Altrimenti, aggiorna la versione nella tabella di contabilità al file .sql più alto eseguito.

Tutto va nel controllo del codice sorgente e ogni installazione ha uno script per aggiornare alla versione più recente con un'unica esecuzione di script (chiamando update.php con la password del database corretta ecc.).Aggiorniamo SVN gli ambienti di staging e di produzione tramite uno script che richiama automaticamente lo script di aggiornamento del database, quindi un aggiornamento del codice viene fornito con gli aggiornamenti del database necessari.

Possiamo anche utilizzare lo stesso script per ricreare da zero l'intero database;semplicemente rilasciamo e ricreiamo il database, quindi eseguiamo lo script che ripopolerà completamente il database.Possiamo anche utilizzare lo script per popolare un database vuoto per i test automatizzati.


Ci sono volute solo poche ore per impostare questo sistema, è concettualmente semplice e tutti ricevono lo schema di numerazione delle versioni, ed è stato prezioso avere la possibilità di andare avanti ed evolvere la progettazione del database, senza dover comunicare o eseguire manualmente le modifiche su tutti i database.

Attenzione però quando incolli le query da phpMyAdmin! Le query generate di solito includono il nome del database, cosa che sicuramente non desideri poiché interromperà i tuoi script!Qualcosa come CREATE TABLE mydb.newtable(...) fallirà se il database sul sistema non si chiama mydb.Abbiamo creato un hook SVN pre-commento che non consentirà i file .sql contenenti il ​​file mydb string, che è un segno sicuro che qualcuno ha copiato/incollato da phpMyAdmin senza un adeguato controllo.

Il mio team crea script per tutte le modifiche al database e invia tali script a SVN, insieme a ogni versione dell'applicazione.Ciò consente modifiche incrementali del database, senza perdere alcun dato.

Per passare da una versione a quella successiva, devi solo eseguire la serie di script di modifica, il tuo database è aggiornato e hai ancora tutti i tuoi dati.Potrebbe non essere il metodo più semplice, ma è sicuramente efficace.

Il problema qui è davvero semplice per gli sviluppatori inserire le proprie modifiche locali nel controllo del codice sorgente per condividerle con il team.Ho affrontato questo problema per molti anni e sono stato ispirato dalle funzionalità di Visual Studio per professionisti di database.Se desideri uno strumento open source con le stesse funzionalità, prova questo: http://dbsourcetools.codeplex.com/ Divertiti, - Nathan.

Se stai ancora cercando soluzioni:stiamo proponendo uno strumento chiamato neXtep designer.È un ambiente di sviluppo di database con il quale puoi mettere l'intero database sotto il controllo della versione.Lavori su un repository controllato dalla versione in cui è possibile tenere traccia di ogni modifica.

Quando è necessario rilasciare un aggiornamento, è possibile impegnare i componenti e il prodotto genererà automaticamente lo script di aggiornamento SQL dalla versione precedente.Naturalmente, puoi generare questo SQL da 2 versioni qualsiasi.

Allora hai molte opzioni:puoi prendere quegli script e inserirli nel tuo SVN con il codice dell'app in modo che venga distribuito dal meccanismo esistente.Un'altra opzione è utilizzare il meccanismo di consegna di neXtep:gli script vengono esportati in qualcosa chiamato "pacchetto di consegna" (script SQL + descrittore XML) e un programma di installazione può comprendere questo pacchetto e distribuirlo su un server di destinazione garantendo coerenza strutturale, controllo delle dipendenze, registrazione della versione installata, ecc.

Il prodotto è GPL ed è basato su Eclipse quindi funziona su Linux, Mac e Windows.Al momento supporta anche Oracle, Mysql e Postgresql (il supporto DB2 è in arrivo).Dai un'occhiata alla wiki dove troverai informazioni più dettagliate:http://www.nextep-softwares.com/wiki

Scarica il tuo schema in un file e aggiungilo al controllo del codice sorgente.Quindi una semplice differenza ti mostrerà cosa è cambiato.

Scott Ambler produce una grande serie di articoli (ed è coautore tra l'altro libro) sul refactoring del database, con l'idea che dovresti essenzialmente applicare i principi e le pratiche TDD per mantenere il tuo schema.Si imposta una serie di unit test della struttura e dei dati seed per il database.Quindi, prima di cambiare qualcosa, modifichi/scrivi test per riflettere quel cambiamento.

Lo facciamo già da un po' e sembra che funzioni.Abbiamo scritto il codice per generare controlli di base del nome della colonna e del tipo di dati in una suite di test unitari.Possiamo eseguire nuovamente questi test in qualsiasi momento per verificare che il database nel checkout SVN corrisponda al database live in cui l'applicazione è effettivamente in esecuzione.

A quanto pare, gli sviluppatori a volte modificano anche il loro database sandbox e trascurano di aggiornare il file di schema in SVN.Il codice dipende quindi da una modifica del database che non è stata archiviata.Questo tipo di bug può essere estremamente difficile da individuare, ma la suite di test lo rileverà immediatamente.Ciò è particolarmente utile se lo hai integrato in un piano di integrazione continua più ampio.

K.Scott Allen ha uno o due articoli decenti sul controllo delle versioni dello schema, che utilizza il concetto di script/migrazioni di aggiornamento incrementale a cui si fa riferimento in altre risposte qui;Vedere http://odetocode.com/Blogs/scott/archive/2008/01/31/11710.aspx.

È un po' a bassa tecnologia e potrebbe esserci una soluzione migliore là fuori, ma potresti semplicemente memorizzare il tuo schema in uno script SQL che può essere eseguito per creare il database.Penso che tu possa eseguire un comando per generare questo script, ma sfortunatamente non conosco il comando.

Quindi, esegui il commit dello script nel controllo del codice sorgente insieme al codice che funziona su di esso.Quando è necessario modificare lo schema insieme al codice, è possibile archiviare lo script insieme al codice che richiede lo schema modificato.Quindi, le differenze sullo script indicheranno le differenze sulle modifiche dello schema.

Con questo script, potresti integrarlo con DBUnit o qualche tipo di script di compilazione, quindi sembra che potrebbe adattarsi ai tuoi processi già automatizzati.

Se utilizzi C#, dai un'occhiata a Subsonic, uno strumento ORM molto utile, ma genera anche script SQL per ricreare il tuo schema e/o i tuoi dati.Questi script possono quindi essere inseriti nel controllo del codice sorgente.

http://subsonicproject.com/

Ho utilizzato la seguente struttura di progetto di database in Visual Studio per diversi progetti e ha funzionato abbastanza bene:

Banca dati

Cambia script

0.PreDeploy.sql

1.SchemaChanges.sql

2.DataChanges.sql

3.Permessi.sql

Crea script

Sproc

Funzioni

Visualizzazioni

Il nostro sistema di compilazione aggiorna quindi il database da una versione a quella successiva eseguendo gli script nel seguente ordine:

1.PreDeploy.sql

2.SchemaChanges.sql

Contenuto della cartella Crea script

2.DataChanges.sql

3.Permessi.sql

Ogni sviluppatore verifica le proprie modifiche per un particolare bug/funzionalità aggiungendo il proprio codice alla fine di ciascun file.Una volta completata e ramificata una versione principale nel controllo del codice sorgente, il contenuto dei file .sql nella cartella Change Scripts viene eliminato.

Usiamo una soluzione molto semplice ma allo stesso tempo efficace.

Per le nuove installazioni, nel repository è presente un file metadata.sql che contiene tutto lo schema del DB, quindi nel processo di creazione utilizziamo questo file per generare il database.

Per gli aggiornamenti, aggiungiamo gli aggiornamenti nel software hardcoded.Lo manteniamo hardcoded perché non ci piace risolvere i problemi prima che diventino realmente un problema, e questo genere di cose non si è rivelato un problema finora.

Quindi nel nostro software abbiamo qualcosa del genere:

RegisterUpgrade(1, 'ALTER TABLE XX ADD XY CHAR(1) NOT NULL;');

Questo codice controllerà se il database è nella versione 1 (che è memorizzata in una tabella creata automaticamente), se è obsoleto, quindi il comando verrà eseguito.

Per aggiornare metadata.sql nel repository, eseguiamo questi aggiornamenti localmente e quindi estraiamo i metadati completi del database.

L'unica cosa che succede di tanto in tanto è dimenticare di eseguire il commit di metadata.sql, ma questo non è un grosso problema perché è facile testarlo durante il processo di compilazione e anche l'unica cosa che potrebbe succedere è fare una nuova installazione con un database obsoleto e lo aggiornò al primo utilizzo.

Inoltre non supportiamo i downgrade, ma è in base alla progettazione, se qualcosa si rompe durante un aggiornamento, ripristiniamo la versione precedente e correggiamo l'aggiornamento prima di riprovare.

Creo cartelle che prendono il nome dalle versioni build e vi inserisco gli script di aggiornamento e downgrade.Ad esempio, potresti avere le seguenti cartelle:1.0.0, 1.0.1 e 1.0.2.Ognuno contiene lo script che ti consente di aggiornare o downgrade il tuo database tra le versioni.

Se un cliente ti chiama per un problema con la versione 1.0.1 e tu stai utilizzando la 1.0.2, riportare il database alla sua versione non sarà un problema.

Nel tuo database, crea una tabella chiamata "schema" in cui inserisci la versione corrente del database.Quindi scrivere un programma in grado di aggiornare o downgrade il tuo database per te è facile.

Proprio come ha detto Joey, se ti trovi in ​​un mondo Rails, usa Migrations.:)

Per il mio attuale progetto PHP utilizziamo l'idea delle migrazioni di rail e abbiamo una directory delle migrazioni in cui conserviamo il titolo del file "migration_XX.sql" dove XX è il numero della migrazione.Attualmente questi file vengono creati manualmente man mano che vengono effettuati gli aggiornamenti, ma la loro creazione potrebbe essere facilmente modificata.

Poi abbiamo uno script chiamato "Migration_watcher" che, poiché siamo in pre-alpha, attualmente viene eseguito ad ogni caricamento di pagina e controlla se esiste un nuovo file migrazione_XX.sql dove XX è più grande dell'attuale versione di migrazione.In tal caso, esegue tutti i file migrazione_XX.sql fino al numero più grande rispetto al database e voilà!le modifiche allo schema sono automatizzate.

Se hai bisogno della possibilità di ripristinare il sistema richiederebbe molte modifiche, ma è semplice e finora ha funzionato molto bene per il nostro team abbastanza piccolo.

Consiglierei di utilizzare Ant (multipiattaforma) per il lato "scripting" (poiché può praticamente parlare con qualsiasi db disponibile tramite jdbc) e Subversion per il repository sorgente.Ant ti consentirà di eseguire il backup del tuo db su file locali, prima di apportare modifiche.1.Backup Schema DB esistente da archiviare tramite ANT 2.Controllo della versione al repository di sovversione tramite ANT 3.invia nuove istruzioni SQL a db tramite Ant

Toad for MySQL ha una funzione chiamata confronto di schemi che ti consente di sincronizzare 2 database.È lo strumento migliore che ho usato finora.

Le migrazioni IMHO hanno un grosso problema:

L'aggiornamento da una versione a un'altra funziona bene, ma eseguire una nuova installazione di una determinata versione potrebbe richiedere un'eternità se si dispone di centinaia di tabelle e una lunga cronologia di modifiche (come facciamo noi).

L'esecuzione dell'intera cronologia dei delta dalla linea di base fino alla versione corrente (per centinaia di database di clienti) potrebbe richiedere molto tempo.

Mi piace il modo in cui gestisce le migrazioni del database.Una migrazione è fondamentalmente l'implementazione di uno script PHP CDbMigration. CDbMigration definisce un up metodo che contiene la logica di migrazione.È anche possibile implementare a down metodo per supportare l’inversione della migrazione.In alternativa, safeUp O safeDown può essere utilizzato per assicurarsi che la migrazione venga eseguita nel contesto di una transazione.

Lo strumento da riga di comando di Yii yiic contiene il supporto per creare ed eseguire migrazioni.Le migrazioni possono essere applicate o annullate, una per una o in batch.La creazione di una migrazione genera codice per l'implementazione di una classe PHP CDbMigration, denominato in modo univoco in base a un timestamp e a un nome di migrazione specificati dall'utente.Tutte le migrazioni precedentemente applicate al database vengono archiviate in una tabella di migrazione.

Per ulteriori informazioni vedere il Migrazione del database articolo dal manuale.

C'è una riga di comando mysql-diff strumento che confronta gli schemi di database, dove lo schema può essere un database live o uno script SQL su disco.È utile per la maggior parte delle attività di migrazione dello schema.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top