Meccanismi per il rilevamento delle modifiche dello schema DB [chiuso]


135

Quali sono i metodi migliori per tracciare e / o automatizzare le modifiche allo schema del 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 (invio di build a un server di gestione temporanea, distribuzione di codice testato su un server di produzione) ma stiamo ancora eseguendo manualmente gli aggiornamenti del database. Vorrei trovare o creare una soluzione che ci consenta di lavorare in modo efficiente su server con ambienti diversi continuando a utilizzare Subversion come backend attraverso il quale gli aggiornamenti di codice e DB vengono inviati ai 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 larga scala (tra più progetti e talvolta più ambienti e lingue)? In tal caso, esiste un codice esistente che semplifica il processo o è meglio implementare la nostra soluzione? Qualcuno ha implementato qualcosa di simile prima e l'ha integrato negli hook post-commit di Subversion, o è una cattiva idea?

Mentre sarebbe preferibile una soluzione che supporti più piattaforme, dobbiamo sicuramente supportare lo stack Linux / Apache / MySQL / PHP poiché la maggior parte del nostro lavoro è su quella piattaforma.

Risposte:


56

Nel mondo di Rails esiste il concetto di migrazioni, script in cui vengono apportate modifiche al database in Ruby piuttosto che un sapore SQL specifico del database. Il codice di migrazione di Ruby finisce per essere convertito nel DDL specifico del database corrente; 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 "up" in cui vengono applicate le modifiche e un metodo "down" 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 loro directory nella directory del progetto e vengono controllate nel controllo della versione proprio come qualsiasi altro codice di progetto.

Questa guida Oracle alle migrazioni di 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. Conosco Ruckusing , un sistema di migrazioni PHP modellato sulle migrazioni di Rails; potrebbe essere quello che stai cercando.


1
Ruckusing FTW: l'abbiamo adattato al nostro sistema db e ne siamo abbastanza soddisfatti.
Piskvor lasciò l'edificio il


50

Usiamo qualcosa di simile a bcwoord per mantenere sincronizzati i nostri schemi di database su 5 diverse installazioni (produzione, gestione temporanea 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 singolo script, update.php e un numero di file numerati 1.sql, 2.sql, 3.sql, ecc. Lo script utilizza una tabella aggiuntiva per memorizzare il numero di versione corrente del Banca dati. I file N.sql sono creati a mano, per passare dalla versione (N-1) alla versione N del database.

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

Lo script di aggiornamento funziona in questo modo:

  • Connettiti al database.
  • Eseguire un backup del database corrente (perché roba sarà andare male) [mysqldump].
  • Creare una tabella di contabilità (chiamata _meta) se non esiste.
  • Leggi la VERSIONE corrente dalla tabella _meta. Supponi 0 se non trovato.
  • Per tutti i file .sql con un numero maggiore di VERSION, eseguili in ordine
  • Se uno dei file ha generato un errore: ripristinare il backup
  • Altrimenti, aggiorna la versione nella tabella di contabilità al file .sql più alto eseguito.

Tutto passa al controllo del codice sorgente e ogni installazione ha uno script da aggiornare all'ultima versione con una singola esecuzione dello script (chiamando update.php con la password del database corretta ecc.). SVN aggiorna gli ambienti di gestione temporanea e di produzione tramite uno script che chiama automaticamente lo script di aggiornamento del database, quindi un aggiornamento del codice viene fornito con gli aggiornamenti del database necessari.

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


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

Fai attenzione quando incolli le query da phpMyAdmin! Quelle query generate di solito includono il nome del database, che sicuramente non si desidera 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 la mydbstringa, che è un segno sicuro che qualcuno copia / incolla da phpMyAdmin senza un controllo adeguato.


Come hai gestito le collisioni? Più sviluppatori cambiano lo stesso elemento nel DB, ad esempio una procedura memorizzata? Questo può accadere se stai lavorando allo stesso nello stesso ramo o hai due linee di sviluppo in corso (due rami)
Asaf Mesika,

Le collisioni erano molto rare; l'unica cosa che è realmente accaduta è che due persone avrebbero provato a creare lo stesso file N.sql. Naturalmente, il primo vince e il secondo è costretto a rinominare il numero più alto successivo e riprovare. Tuttavia, non avevamo il controllo delle versioni del database su un ramo.
rix0rrr,

12

Il mio team esegue lo scripting di 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 alla successiva, devi solo eseguire il set di script di modifica e il tuo database è aggiornato e hai ancora tutti i tuoi dati. Potrebbe non essere il metodo più semplice, ma sicuramente è efficace.


1
come si fa a scrivere tutte le modifiche?
Smith,

10

Il problema qui sta davvero rendendo facile per gli sviluppatori scrivere le proprie modifiche locali nel controllo del codice sorgente da condividere con il team. Ho affrontato questo problema per molti anni ed è stato ispirato dalla funzionalità dei professionisti di Visual Studio per Database. Se vuoi uno strumento open source con le stesse funzionalità, prova questo: http://dbsourcetools.codeplex.com/ Buon divertimento, Nathan.


10

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

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

Quindi hai molte opzioni: puoi prendere quegli script e inserirli nel tuo SVN con il tuo codice app in modo che vengano distribuiti dal tuo meccanismo esistente. Un'altra opzione è quella di utilizzare il meccanismo di consegna di neXtep: gli script vengono esportati in qualcosa chiamato "pacchetto di consegna" (script SQL + descrittore XML) e un installatore può capire questo pacchetto e distribuirlo su un server di destinazione garantendo coerenza strcuturale, dipendenza controllare, registrare la versione installata, ecc.

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


Sembra interessante. Ha anche un'interfaccia a riga di comando o ne è prevista una?
Piskvor lasciò l'edificio il

8

Scott Ambler produce una grande serie di articoli (e co-autore di un libro ) sul refactoring del database, con l'idea che si dovrebbero essenzialmente applicare i principi e le pratiche TDD per mantenere il proprio schema. È possibile impostare una serie di test di unità dati di struttura e seed per il database. Quindi, prima di cambiare qualsiasi cosa, modifichi / scrivi i test per riflettere quel cambiamento.

Lo stiamo facendo da un po 'di tempo e sembra funzionare. Abbiamo scritto codice per generare controlli di nome di colonna e tipo di dati di base in una suite di unit test. È possibile rieseguire tali test in qualsiasi momento per verificare che il database nel checkout SVN corrisponda al db live in cui l'applicazione è effettivamente in esecuzione.

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


7

Scarica lo schema in un file e aggiungilo al controllo del codice sorgente. Quindi un semplice diff ti mostrerà cosa è cambiato.


1
Il dump deve essere in SQL, come un mysqldump, i dump di Oracle sono binari.
Osama Al-Maadeed,

7
C'è anche un problema più fondamentale con la differenza dello schema. Come si fa a differenziare un rilascio di colonna + aggiungi da un nome di colonna. La risposta è semplice: non puoi. Questo è il motivo per cui è necessario registrare le effettive operazioni di modifica dello schema.
psp

Il diff mostrerà che una colonna è sparita, mentre l'altra è apparsa (a meno che non abbiano lo stesso nome) e la maggior parte delle volte è sufficiente. Lo scripting di ogni modifica dello schema è un buon modo di procedere, ovviamente: in Drupal questo è gestito da un hook speciale, ad esempio.
deadprogrammer


5

È un po 'a bassa tecnologia e potrebbe esserci una soluzione migliore là fuori, ma potresti semplicemente archiviare 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, impegna lo script nel controllo del codice sorgente insieme al codice che funziona su di esso. Quando è necessario modificare lo schema insieme al codice, è possibile effettuare il check-in dello script insieme al codice che richiede lo schema modificato. Quindi, le differenze sullo script indicano differenze nelle modifiche allo schema.

Con questo script, è possibile integrarlo con DBUnit o qualche tipo di script di compilazione, quindi sembra che si adatti ai processi già automatizzati.


Sì, è praticamente quello che abbiamo in atto in questo momento. Sfortunatamente ciò non ci offre un modo semplice per modificare i database esistenti: lo script SQL generato da mysqldump presuppone che tu stia creando la tabella da zero (o sovrascrivendo una tabella se esiste). Abbiamo bisogno di qualcosa di un po 'più high-tech perché deve applicare una sequenza di istruzioni ALTER TABLE al database e per farlo correttamente deve essere consapevole dello stato corrente del database.
pix0r

5

Se stai usando 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 messi nel controllo del codice sorgente.

http://subsonicproject.com/


Sembra essere un URL morto a partire da questo momento.
Mark Schultheiss,

5

Ho usato la seguente struttura di progetto del 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.Permissions.sql

Crea script

sprocs

funzioni

Visualizzazioni

Il nostro sistema di generazione quindi aggiorna il database da una versione alla successiva eseguendo gli script nel seguente ordine:

1.PreDeploy.sql

2.SchemaChanges.sql

Contenuto della cartella Crea script

2.DataChanges.sql

3.Permissions.sql

Ogni sviluppatore controlla le proprie modifiche per un determinato bug / funzionalità aggiungendo il proprio codice alla fine di ogni file. Una volta completata e ramificata una versione principale nel controllo del codice sorgente, i contenuti dei file .sql nella cartella Change Scripts vengono eliminati.


5

Usiamo una soluzione molto semplice ma efficace.

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

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

Quindi nel nostro software abbiamo qualcosa del genere:

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

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

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

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

Inoltre non supportiamo i downgrade, ma è in base alla progettazione, se qualcosa si interrompe su un aggiornamento, abbiamo ripristinato la versione precedente e riparato l'aggiornamento prima di riprovare.


4

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

Se un cliente o un cliente ti chiama con un problema con la versione 1.0.1 e stai utilizzando 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 che può aggiornare o eseguire il downgrade del database per te è facile.

Proprio come ha detto Joey, se sei in un mondo di Rails, usa Migrations. :)


3

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

Quindi abbiamo uno script chiamato "Migration_watcher" che, come siamo in pre-alpha, attualmente viene eseguito su ogni caricamento di pagina e verifica se esiste un nuovo file migration_XX.sql in cui XX è più grande della versione di migrazione corrente. In tal caso, esegue tutti i file migration_XX.sql fino al numero più grande rispetto al database e voilà! le modifiche allo schema sono automatizzate.

Se si richiede la possibilità di ripristinare il sistema richiederebbe un sacco di modifiche, ma è semplice e finora ha funzionato molto bene per il nostro team abbastanza piccolo.


3

Consiglierei di usare Ant (multipiattaforma) per il lato "scripting" (dal momento che può praticamente parlare con qualsiasi db là fuori tramite jdbc) e Subversion per il repository di origine. Ant ti consentirà di "eseguire il backup" del tuo db in file locali, prima di apportare modifiche. 1. eseguire il backup dello schema db esistente su file tramite Ant 2. controllo versione nel repository Subversion tramite Ant 3. inviare nuove istruzioni sql a db tramite Ant


3

Toad per MySQL ha una funzione chiamata schema compare che consente di sincronizzare 2 database. È lo strumento migliore che ho usato finora.


3

Mi piace il modo in cui Yii gestisce le migrazioni del database. Una migrazione è fondamentalmente un'implementazione di script PHP CDbMigration. CDbMigrationdefinisce un upmetodo che contiene la logica di migrazione. È anche possibile implementare un downmetodo per supportare l'inversione della migrazione. In alternativa, safeUpo safeDownpuò essere utilizzato per assicurarsi che la migrazione venga eseguita nel contesto di una transazione.

Lo strumento da riga di comando di Yii yiiccontiene supporto per creare ed eseguire migrazioni. Le migrazioni possono essere applicate o invertite, una alla volta o in un batch. La creazione di una migrazione genera un codice per l'implementazione di una classe PHP CDbMigration, denominata in modo univoco in base a un timestamp e un nome di migrazione specificato dall'utente. Tutte le migrazioni che sono state precedentemente applicate al database sono archiviate in una tabella di migrazione.

Per ulteriori informazioni, consultare l' articolo sulla migrazione del database dal manuale.



2

Le migrazioni IMHO hanno un grosso problema:

L'aggiornamento da una versione all'altra funziona bene, ma fare una nuova installazione di una data versione potrebbe richiedere un'eternità se hai centinaia di tabelle e una lunga storia di modifiche (come facciamo noi).

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


0

Esiste uno strumento mysql-diff della riga di comando che confronta gli schemi del database, in cui lo schema può essere un database attivo o uno script SQL sul disco. È utile per la maggior parte delle attività di migrazione dello schema.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.