Come gestite i database in sviluppo, test e produzione?


171

Ho avuto difficoltà a trovare buoni esempi di come gestire schemi e dati di database tra server di sviluppo, test e produzione.

Ecco la nostra configurazione. Ogni sviluppatore ha una macchina virtuale che esegue la nostra app e il database MySQL. È la loro sandbox personale a fare quello che vogliono. Attualmente, gli sviluppatori apporteranno una modifica allo schema SQL e eseguiranno il dump del database in un file di testo che eseguono il commit in SVN.

Desideriamo distribuire un server di sviluppo a integrazione continua che eseguirà sempre l'ultimo codice di commit. Se lo facciamo ora, ricaricherà il database da SVN per ogni build.

Abbiamo un server di prova (virtuale) che esegue "rilascia candidati". La distribuzione sul server di prova è attualmente un processo molto manuale e di solito mi coinvolge caricando l'ultimo SQL da SVN e modificandolo. Inoltre, i dati sul server di prova sono incoerenti. Si finisce con tutti i dati di test che l'ultimo sviluppatore ha commesso sul suo server sandbox.

Dove tutto si rompe è la distribuzione in produzione. Poiché non è possibile sovrascrivere i dati in tempo reale con i dati di test, ciò comporta la ricostruzione manuale di tutte le modifiche allo schema. Se ci sono state molte modifiche allo schema o script di conversione per manipolare i dati, questo può diventare davvero peloso.

Se il problema fosse solo lo schema, sarebbe un problema più semplice, ma ci sono dati "di base" nel database che vengono aggiornati anche durante lo sviluppo, come i metadati nelle tabelle di sicurezza e autorizzazioni.

Questa è la più grande barriera che vedo nel passaggio verso l'integrazione continua e le build in un solo passaggio. Come lo risolvi?


Una domanda di follow-up: come tenere traccia delle versioni del database in modo da sapere quali script eseguire per aggiornare una determinata istanza del database? Una tabella delle versioni come Lance menziona sotto la procedura standard?


Grazie per il riferimento a Tarantino. Non sono in un ambiente .NET, ma ho trovato molto utile la loro pagina wiki DataBaseChangeMangement . Soprattutto questa presentazione Powerpoint (.ppt)

Scriverò uno script Python che controlla i nomi degli *.sqlscript in una determinata directory rispetto a una tabella nel database ed esegue quelli che non sono presenti in ordine in base a un numero intero che costituisce la prima parte del nome file. Se è una soluzione abbastanza semplice, come sospetto che sarà, la posterò qui.


Ho una sceneggiatura funzionante per questo. Gestisce l'inizializzazione del DB se non esiste e l'esecuzione degli script di aggiornamento, se necessario. Esistono anche opzioni per cancellare un database esistente e importare dati di test da un file. Sono circa 200 righe, quindi non lo posterò (anche se potrei metterlo su pastebin se c'è interesse).



"Scriverò uno script Python che controlla i nomi degli script * .sql in una determinata directory rispetto a una tabella nel database ed esegue quelli che non sono lì in ordine in base a un numero intero che costituisce la prima parte di il nome del file. Se si tratta di una soluzione piuttosto semplice, come sospetto che sarà, la posterò qui. " Sembra che tu stia implementando flyway.
masterxilo,

Risposte:


53

Ci sono un paio di buone opzioni. Non userei la strategia "ripristina un backup".

  1. Effettua lo script di tutte le modifiche allo schema e chiedi al tuo server CI di eseguire quegli script sul database. Avere una tabella delle versioni per tenere traccia della versione corrente del database ed eseguire gli script solo se sono per una versione più recente.

  2. Utilizzare una soluzione di migrazione. Queste soluzioni variano in base alla lingua, ma per .NET utilizzo Migrator.NET. Ciò consente di eseguire la versione del database e spostarsi su e giù tra le versioni. Lo schema è specificato nel codice C #.


28

I tuoi sviluppatori devono scrivere script di modifica (modifica dello schema e dei dati) per ogni bug / funzionalità su cui lavorano, non semplicemente scaricare l'intero database nel controllo del codice sorgente. Questi script aggiorneranno l'attuale database di produzione alla nuova versione in sviluppo.

Il processo di compilazione può ripristinare una copia del database di produzione in un ambiente appropriato ed eseguire tutti gli script dal controllo del codice sorgente su di esso, che aggiornerà il database alla versione corrente. Lo facciamo quotidianamente per assicurarci che tutti gli script vengano eseguiti correttamente.


13

Dai un'occhiata a come fa Ruby on Rails.

Innanzitutto ci sono i cosiddetti file di migrazione, che trasformano sostanzialmente lo schema e i dati del database dalla versione N alla versione N + 1 (o in caso di downgrade dalla versione N + 1 a N). Il database ha una tabella che indica la versione corrente.

I database dei test vengono sempre puliti prima dei test unitari e popolati con dati fissi dai file.


10

Il libro Database di refactoring: Evolutionary Database Design potrebbe darti alcune idee su come gestire il database. Una versione breve è leggibile anche su http://martinfowler.com/articles/evodb.html

In un progetto PHP + MySQL ho avuto il numero di revisione del database memorizzato nel database e quando il programma si collega al database, controllerà prima la revisione. Se il programma richiede una revisione diversa, aprirà una pagina per l'aggiornamento del database. Ogni aggiornamento è specificato nel codice PHP, che cambierà lo schema del database e migrerà tutti i dati esistenti.


5
  • Dai un nome ai tuoi database come segue - dev_<<db>> , tst_<<db>> , stg_<<db>> , prd_<<db>>(Ovviamente non dovresti mai hardcodificare i nomi db
  • Quindi si sarebbe in grado di distribuire anche il diverso tipo di db sullo stesso server fisico (non lo consiglio, ma potrebbe essere necessario ... se le risorse sono limitate)
  • Assicurati di essere in grado di spostare i dati tra quelli automaticamente
  • Separare gli script di creazione db dalla popolazione = Dovrebbe essere sempre possibile ricreare il db da zero e popolarlo (dalla vecchia versione del db o dall'origine dati esterna
  • non utilizzare stringhe di connessione hardcode nel codice (anche non nei file di configurazione) - utilizzare nei modelli di stringa di connessione file di configurazione, che vengono popolati dinamicamente, ogni riconfigurazione di application_layer che deve essere ricompilata è MALE
  • usa il versioning del database e il versioning degli oggetti db - se puoi permetterti usa prodotti pronti, se non sviluppi qualcosa da solo
  • traccia ogni modifica DDL e salvala in una tabella di cronologia ( esempio qui )
  • Backup GIORNALIERI! Verifica la velocità con cui saresti in grado di ripristinare qualcosa perso da un backup (usa gli script di ripristino automatico
  • anche il tuo database DEV e il PROD hanno esattamente lo stesso script di creazione che avrai problemi con i dati, quindi consenti agli sviluppatori di creare la copia esatta del prod e giocare con esso (so che riceverò dei vantaggi per questo, ma cambio nel la mentalità e il processo aziendale ti costeranno molto meno quando la merda colpisce il fan - quindi obbliga i programmatori a sottoscrivere legalmente qualunque cosa faccia, ma assicurati che questo

L'ultimo punto è davvero l'umore. Se è necessario, mostra che la definizione del progetto è interrotta. Lo sviluppo deve condurre prima della produzione. Se i dati di produzione inducono effetti collaterali, mostrano problemi maggiori. Pulisci i dati di produzione. Chiarisci anche l'ultimo passaggio con il responsabile della protezione dei dati, se c'è motivo - come suggerisci - che i dati in tempo reale debbano essere su sistemi di sviluppo, controlla se ciò è legalmente applicabile. Anche una copia esatta dei dati di produzione rallenta notevolmente lo sviluppo e l'integrazione. Prendi in considerazione un processo meno costoso se non puoi permetterti tale lusso.
Hacre,

Il fatto è che durante lo sviluppo non è nemmeno possibile prevedere tutti i casi angolari nel flusso di controllo e le variazioni nella qualità dei dati che si verificheranno nella produzione. Se ci si trova in un corpo così grande, è necessario implementare problemi legali rispetto a una sorta di soluzione di scrambling e / o mascheramento dei dati, che aggiunge ulteriore livello di complessità, ma deve comunque preservare gli aspetti di qualità dei dati che hanno causato il bug in primo luogo comunque ...
Yordan Georgiev,

4

Questo è qualcosa di cui sono costantemente insoddisfatto: la nostra soluzione a questo problema è. Per diversi anni abbiamo mantenuto uno script di modifica separato per ogni versione. Questo script conterrebbe i delta dell'ultima versione di produzione. Con ogni versione dell'applicazione, il numero di versione aumenterebbe, fornendo qualcosa di simile al seguente:

  • dbChanges_1.sql
  • dbChanges_2.sql
  • ...
  • dbChanges_n.sql

Questo ha funzionato abbastanza bene fino a quando non abbiamo iniziato a mantenere due linee di sviluppo: Trunk / Mainline per il nuovo sviluppo e un ramo di manutenzione per correzioni di errori, miglioramenti a breve termine, ecc. Inevitabilmente, è emersa la necessità di apportare modifiche allo schema nel ramo. A questo punto, avevamo già dbChanges_n + 1.sql nel trunk, quindi abbiamo finito con uno schema come il seguente:

  • dbChanges_n.1.sql
  • dbChanges_n.2.sql
  • ...
  • dbChanges_n.3.sql

Ancora una volta, questo ha funzionato abbastanza bene, fino a quando un giorno abbiamo alzato lo sguardo e abbiamo visto 42 script delta nella linea principale e 10 nel ramo. ARGH!

Al giorno d'oggi manteniamo semplicemente uno script delta e lasciamo che sia la versione SVN, ovvero sovrascriviamo lo script ad ogni versione. E evitiamo di apportare modifiche allo schema nei rami.

Quindi, non sono soddisfatto neanche di questo. Mi piace molto il concetto di migrazioni da Rails. Sono rimasto piuttosto affascinato da LiquiBase . Supporta il concetto di refactoring incrementale del database. Vale la pena dare un'occhiata e lo vedrò in dettaglio presto. Qualcuno ha esperienza con esso? Sarei molto curioso di sapere dei tuoi risultati.


4

Puoi anche guardare usando uno strumento come SQL Compare per scrivere la differenza tra le varie versioni di un database, permettendoti di migrare rapidamente tra le versioni


3

Abbiamo una configurazione molto simile all'OP.

Gli sviluppatori si sviluppano in VM con DB privati.

[Gli sviluppatori si impegneranno presto in filiali private]

Il test viene eseguito su macchine diverse (attualmente in VM ospitato su un server) [Presto verrà eseguito dal server Hudson CI]

Test caricando il dump di riferimento nel db. Applicare le patch dello schema degli sviluppatori, quindi applicare le patch dei dati degli sviluppatori

Quindi eseguire i test dell'unità e del sistema.

La produzione viene distribuita ai clienti come installatori.

Cosa facciamo:

Prendiamo un dump dello schema del nostro DB sandbox. Quindi un dump di dati sql. Differiamo dalla precedente linea di base. quella coppia di delta consiste nell'aggiornamento da n-1 a n.

configuriamo i dump e i delta.

Quindi per installare la versione N CLEAN eseguiamo il dump in un db vuoto. Per applicare le patch, applicare le patch intermedie.

(Juha ha menzionato l'idea di Rail di avere una tabella che registri l'attuale versione del DB è buona e dovrebbe rendere meno complicata l'installazione degli aggiornamenti.)

I delta e le discariche devono essere rivisti prima del beta test. Non riesco a vedere nulla di simile poiché ho visto gli sviluppatori inserire da soli gli account di prova nel DB.


3

Temo di essere d'accordo con altri poster. Gli sviluppatori devono scrivere le loro modifiche.

In molti casi una semplice ALTER TABLE non funziona, è necessario modificare anche i dati esistenti: gli sviluppatori devono pensare a quali migrazioni sono necessarie e assicurarsi che siano copiate correttamente (ovviamente è necessario testarle attentamente ad un certo punto in il ciclo di rilascio).

Inoltre, se hai qualche senso, spingi i tuoi sviluppatori a eseguire il rollback degli script per le loro modifiche, in modo che possano essere ripristinati se necessario. Anche questo dovrebbe essere testato, per garantire che il loro rollback non solo venga eseguito senza errori, ma lasci il DB nello stesso stato di prima (ciò non è sempre possibile o desiderabile, ma è una buona regola la maggior parte del tempo) .

Come lo colleghi a un server CI, non lo so. Forse il tuo server CI deve avere un'istantanea di build nota, su cui ripristina ogni notte e quindi applica tutte le modifiche da allora. Questo è probabilmente il migliore, altrimenti uno script di migrazione interrotto non romperà solo la build di quella notte, ma tutti quelli successivi.


1

Dai un'occhiata a dbdeploy , ci sono già strumenti Java e .net, potresti seguire i loro standard per i layout dei file SQL e la tabella delle versioni dello schema e scrivere la tua versione di Python.


1

Stiamo usando la riga di comando mysql-diff : genera una differenza tra due schemi di database (da DB live o script) come script ALTER. mysql-diff viene eseguito all'avvio dell'applicazione e, se lo schema viene modificato, viene segnalato allo sviluppatore. Quindi gli sviluppatori non devono scrivere ALTER manualmente, gli aggiornamenti dello schema avvengono in modo semi-automatico.



0

Ho scritto uno strumento che ( collegandosi a Open DBDiff ) confronta gli schemi di database e ti suggerirà script di migrazione. Se apporti una modifica che elimina o modifica i dati, genererà un errore, ma fornirà un suggerimento per lo script (ad es. Quando manca una colonna nel nuovo schema, controllerà se la colonna è stata rinominata e crea xx - generated script.sql.suggestion contenente un'istruzione rename).

http://code.google.com/p/migrationscriptgenerator/ Solo SQL Server temo :( È anche piuttosto alfa, ma è MOLTO basso attrito (in particolare se lo si combina con Tarantino o http://code.google .com / p / simplescriptrunner / )

Il modo in cui lo uso è di avere un progetto di script SQL nel tuo .sln. È inoltre disponibile localmente un database db_next a cui si apportano le modifiche (utilizzando Management Studio o NHibernate Schema Export o LinqToSql CreateDatabase o qualcosa del genere). Quindi esegui migrationscriptgenerator con i DB _dev e _next, che crea. gli script di aggiornamento SQL per la migrazione.


0

Per il database Oracle usiamo gli strumenti oracle-ddl2svn .

Questo strumento automatizza il prossimo processo

  1. per ogni schema db ottenere lo schema ddls
  2. metterlo in versione contol

le modifiche tra istanze sono state risolte manualmente

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.