Ci sono state alcune discussioni sulla wiki della comunità SO sul fatto che gli oggetti del database dovrebbero essere controllati dalla versione. Tuttavia, non ho visto molte discussioni sulle migliori pratiche per la creazione di un processo di automazione build per gli oggetti del database.
Questo è stato un punto di discussione polemico per il mio team, in particolare dal momento che gli sviluppatori e i DBA hanno spesso obiettivi, approcci e preoccupazioni diversi nella valutazione dei vantaggi e dei rischi di un approccio di automazione all’implementazione del database.
Mi piacerebbe sentire alcune idee dalla comunità SO su quali pratiche sono state efficaci nel mondo reale.
Mi rendo conto che è in qualche modo soggettivo quali sono le pratiche migliori, ma penso che un buon dialogo su quale lavoro possa essere utile a molte persone.
Ecco alcune delle mie domande sul teaser sulle aree di interesse in questo argomento. Questi non sono intesi per essere una lista definitiva – piuttosto un punto di partenza per le persone per aiutare a capire quello che sto cercando.
Trovo lo SQL come codice sorgente quando ansible
Se riesco a scriverlo nello standard SQL conforms allo standard, in genere viene inserito in un file nel mio controllo sorgente. Il file definirà il più ansible, come le dichiarazioni SP, Table CREATE.
Includo anche i dati fittizi per i test nel controllo del codice sorgente:
E poi estrapro tutte le mie query SQL in modo che possa build l’intero progetto per MySQL, Oracle, MSSQL o qualsiasi altra cosa.
L’automazione di build e test utilizza questi script di build in quanto sono importanti quanto l’origine dell’app e verifica tutto dall’integrità tramite trigger, procedure e registrazione.
Utilizziamo l’integrazione continua tramite TeamCity. Ad ogni controllo al controllo del codice sorgente, il database e tutti i dati del test vengono ricostruiti da zero, quindi il codice, quindi i test delle unità vengono eseguiti sul codice. Se stai usando uno strumento di generazione del codice come CodeSmith, può anche essere inserito nel tuo processo di generazione per generare il tuo livello di accesso ai dati fresco con ogni build, assicurandoti che tutti i livelli “si abbinino” e non producano errori dovuti a parametri SP non corrispondenti o colonne mancanti.
Ogni build ha una propria collezione di script SQL che sono memorizzati nella directory $ project \ SQL \ nel controllo del codice sorgente, assegnato un prefisso numerico ed eseguito nell’ordine. In questo modo, stiamo esercitando la nostra procedura di implementazione ad ogni build.
A seconda della tabella di ricerca, la maggior parte dei nostri valori di ricerca viene anche memorizzata negli script ed eseguita per assicurarsi che i dati di configurazione siano quelli che ci aspettiamo, ad esempio, “reason_codes” o “country_codes”. In questo modo possiamo modificare i dati di ricerca in dev, testarli e quindi “promuoverli” attraverso QA e produzione, invece di utilizzare uno strumento per modificare i valori di ricerca nella produzione, che può essere pericoloso per il tempo di attività.
Creiamo anche una serie di script di “rollback” che annullano le modifiche al nostro database, nel caso in cui una build in produzione diventi vaga. È ansible testare gli script di rollback eseguendoli, quindi rieseguire i test delle unità per la versione di build precedente alla propria, dopo l’esecuzione degli script di distribuzione.
Facendo domande “teaser” sembra che tu sia più interessato a una discussione rispetto all’opinione di qualcuno sulle risposte finali. La mailing list triggers (> 2500 membri) agileDatabases ha affrontato molte di queste domande ed è, nella mia esperienza, un forum sofisticato e civile per questo tipo di discussione.
Sono sostanzialmente d’accordo con ogni risposta data da van . Per saperne di più, la mia linea di base per la gestione dei database è la serie di K. Scott Allen (assolutamente da leggere, IMHO. E anche l’opinione di Jeff sembra).
Create.sql
. Questo può includere l’inserimento di dati statici (elenchi …). Create.sql
: Create.cmd
. Il suo objective è principalmente quello di verificare i prerequisiti (strumenti, variabili d’ambiente …) e inviare parametri allo script SQL. Può anche caricare in blocco i dati statici dai file CSV per problemi di prestazioni. Create.cmd
. IMHO, il caricamento dinamico dei dati dovrebbe richiedere un altro passo, a seconda del tuo ambiente. Gli sviluppatori vorranno caricare il loro database con dati di test, spazzatura o nessun dato, mentre all’altro capo della produzione i responsabili della produzione vorranno caricare i dati di produzione. Prenderò in considerazione la possibilità di memorizzare i dati di test anche nel controllo del codice sorgente (per facilitare il test dell’unità, ad esempio).
Una volta che la prima versione del database è stata messa in produzione, non sarà necessario solo creare script (principalmente per gli sviluppatori), ma anche aggiornare gli script (basati sugli stessi principi):
Upgrade.sql
(che può chiamarne altri) che consente di aggiornare la versione N-1 alla versione N (N essendo la versione rilasciata). Conservo questo script in una cartella denominata N-1
. Upgrade.cmd
. Può recuperare la versione corrente (CV) del database tramite una semplice istruzione SELECT, avviare lo script Upgrade.sql
memorizzato nella cartella CV
e eseguire il ciclo finché non viene trovata alcuna cartella. In questo modo, è ansible eseguire automaticamente l’aggiornamento da, ad esempio, da N-3 a N. I problemi con questo sono:
Per quanto riguarda il tipo di oggetti di database che vuoi avere sotto il controllo del codice sorgente? Bene, direi il più ansible, ma non di più 😉 Se si desidera creare utenti con password, ottenere loro una password predefinita (login / login, pratico per scopi di test unitari), e rendere la password modificare un’operazione manuale . Questo succede molto con Oracle, dove gli schemi sono anche utenti …
+1 per Liquibase : LiquiBase è una libreria open source (LGPL), indipendente dal database per il monitoraggio, la gestione e l’applicazione delle modifiche al database. Si basa su una premessa semplice: tutte le modifiche al database (struttura e dati) sono archiviate in modo descrittivo basato su XML e controllate nel controllo del codice sorgente. Il punto positivo è che le modifiche di DML sono memorizzate semanticamente, non solo diff, in modo da poter monitorare lo scopo delle modifiche.
Potrebbe essere combinato con il controllo della versione GIT per una migliore interazione. Configurerò il nostro ambiente di sviluppo per provarlo.
Inoltre, è ansible utilizzare Maven, i sistemi di build Ant per creare codice di produzione dagli script.
Tha minus è che LiquiBase non si integra in IDE SQL diffusi e dovresti fare da solo le operazioni di base.
In aggiunta a questo, è ansible utilizzare DBUnit per il test DB: questo strumento consente di utilizzare script di generazione dati per testare l’ambiente di produzione con la pulizia successiva.
A PARER MIO:
Abbiamo affrontato tutti i problemi menzionati con le modifiche al codice, la fusione, la riscrittura nel nostro database di produzione di fatturazione. Questo argomento è ottimo per scoprire tutte queste cose.
Abbiamo il nostro progetto Silverlight con database MSSQL nel controllo di versione Git. Il modo più semplice è assicurarsi di avere un database snellito (per quanto riguarda i contenuti) e fare un dump completo di fe Visual Studio. Quindi puoi eseguire “sqlcmd” dal tuo script di build per ricreare il database su ogni macchina di sviluppo.
Per la distribuzione questo non è ansible poiché i database sono troppo grandi: questo è il motivo principale per averli in un database in primo luogo.
Sono fermamente convinto che un DB dovrebbe essere parte del controllo del codice sorgente e in larga parte parte del processo di compilazione. Se si trova nel controllo del codice sorgente, ho le stesse protezioni per la sicurezza del codice quando scrivo una procedura memorizzata in SQL come faccio quando scrivo una class in C #. Lo faccio includendo una directory di script DB sotto il mio albero dei sorgenti. Questa directory di script non ha necessariamente un file per un object nel database. Quello sarebbe un dolore nel sedere! Sviluppo nel mio db proprio come farei nel mio progetto di codice. Poi, quando sono pronto per il check-in, faccio una diff tra l’ultima versione del mio database e quella attuale su cui sto lavorando. Uso SQL Compare per questo e genera uno script di tutte le modifiche. Questo script viene quindi salvato nella mia directory db_update con una convenzione di denominazione specifica 1234_TasksCompletedInThisIteration in cui il numero è il numero successivo nel set di script già presenti e il nome descrive cosa viene eseguito in questo check in. Lo faccio in questo modo perché parte del mio processo di compilazione comincio con un nuovo database che viene quindi compilato in modo programmatico utilizzando gli script in questa directory. Ho scritto un task NAnt personalizzato che scorre ogni script eseguendo il suo contenuto sul db bare. Ovviamente se ho bisogno di alcuni dati per andare nel db allora ho anche degli script di inserimento dati. Questo ha anche molti vantaggi. Uno, tutta la mia roba è in versione. Due, ogni build è una build nuova, il che significa che non ci sarà nulla di subdolo nel processo di sviluppo (come i dati sporchi che causano stranezze nel sistema). Tre, quando un nuovo ragazzo viene aggiunto al team di sviluppo, hanno semplicemente bisogno di ottenere l’ultimo e il loro dev locale è costruito per loro al volo. Quattro, posso eseguire test case (non l’ho chiamato “unit test”!) Sul mio database quando lo stato del database viene resettato con ogni build (cioè posso testare i miei repository senza preoccuparmi di aggiungere dati di test al db).
Questo non è per tutti.
Questo non è per ogni progetto. Di solito lavoro su progetti di campi verdi che mi consentono questa comodità!
Piuttosto che entrare in discussioni con la torre bianca, ecco una soluzione che ha funzionato molto bene per me sui problemi del mondo reale.
Costruire un database da zero può essere riassunto come la gestione degli script sql.
DBdeploy è uno strumento che controllerà lo stato corrente di un database, ad esempio quali script sono stati precedentemente eseguiti contro di esso, quali script sono disponibili per essere eseguiti e quindi quali script sono necessari per essere eseguiti.
Quindi raccoglierà tutti gli script necessari ed eseguirli. Quindi registra quali script sono stati eseguiti.
Non è lo strumento più bello o il più complesso, ma con una gestione attenta può funzionare molto bene. È open source e facilmente estensibile. Una volta che l’esecuzione degli script è gestita bene, aggiungere alcuni componenti extra come uno script di shell che controlla gli ultimi script ed esegue dbdeploy su una particolare istanza è facilmente raggiungibile.
Guarda una buona introduzione qui:
Potresti scoprire che Liquibase gestisce molto di ciò che stai cercando.
Ogni sviluppatore dovrebbe avere il proprio database locale e utilizzare il controllo del codice sorgente per pubblicare nel team. La mia soluzione è qui: http://dbsourcetools.codeplex.com/ Divertiti, – Nathan