Come dovresti costruire il tuo database dal controllo del codice sorgente?


103

Ci sono state alcune discussioni sul wiki della comunità SO riguardo al fatto che gli oggetti del database debbano essere controllati dalla versione. Tuttavia, non ho visto molte discussioni sulle best practice per la creazione di un processo di automazione della compilazione per gli oggetti di database.

Questo è stato un punto di discussione controverso per il mio team, soprattutto perché gli sviluppatori e gli amministratori di database hanno spesso obiettivi, approcci e preoccupazioni diversi quando valutano i vantaggi e i rischi di un approccio di automazione alla distribuzione del database.

Vorrei ascoltare alcune idee dalla comunità SO su quali pratiche sono state efficaci nel mondo reale.

Mi rendo conto che è in qualche modo soggettivo quali siano le pratiche migliori, ma penso che un buon dialogo su quale lavoro potrebbe essere utile a molte persone.

Ecco alcune delle mie domande teaser sulle aree di interesse in questo argomento. Questi non vogliono essere un elenco definitivo, ma piuttosto un punto di partenza per le persone che mi aiutano a capire cosa sto cercando.

  1. Gli ambienti di test e di produzione dovrebbero essere costruiti dal controllo del codice sorgente?
    • Dovrebbero essere entrambi costruiti utilizzando l'automazione o la produzione dovrebbe essere costruita copiando oggetti da un ambiente di test stabile e finalizzato?
    • Come gestisci le potenziali differenze tra gli ambienti di test e di produzione negli script di distribuzione?
    • Come si verifica che gli script di distribuzione funzioneranno con la stessa efficacia con la produzione come in test?
  2. Quali tipi di oggetti dovrebbero essere controllati dalla versione?
    • Solo codice (procedure, pacchetti, trigger, java, ecc.)?
    • Indici?
    • Vincoli?
    • Definizioni delle tabelle?
    • Script di modifica della tabella? (es. ALTER script)
    • Qualunque cosa?
  3. Quali tipi di oggetti non dovrebbero essere controllati dalla versione?
    • Sequenze?
    • Borse di studio?
    • Profili utente?
  4. Come dovrebbero essere organizzati gli oggetti del database nel repository SCM?
    • Come gestisci cose una tantum come script di conversione o script ALTER?
    • Come gestisci il ritiro degli oggetti dal database?
    • Chi dovrebbe essere responsabile della promozione degli oggetti dallo sviluppo al livello di test?
    • Come coordini le modifiche di più sviluppatori?
    • Come gestisci la ramificazione per gli oggetti di database utilizzati da più sistemi?
  5. Quali eccezioni, se del caso, possono essere ragionevolmente fatte a questo processo?
    • Problemi di sicurezza?
    • Dati con problemi di anonimizzazione?
    • Script che non possono essere completamente automatizzati?
  6. Come puoi rendere il processo resiliente e applicabile?
    • All'errore dello sviluppatore?
    • A problemi ambientali imprevisti?
    • Per il ripristino di emergenza?
  7. Come convincere i responsabili delle decisioni che i vantaggi di DB-SCM giustificano davvero il costo?
    • Prove aneddotiche?
    • Ricerca di settore?
    • Consigli di best practice del settore?
    • Ricorsi alle autorità riconosciute?
    • Analisi costi benefici?
  8. Chi dovrebbe "possedere" oggetti di database in questo modello?
    • Gli sviluppatori?
    • DBA?
    • Analisti di dati?
    • Più di una?

3
La profondità di questa domanda richiede una taglia.
Greg D,

Risposte:


53

Ecco alcune risposte alle tue domande:

  1. Gli ambienti di test e di produzione dovrebbero essere costruiti dal controllo del codice sorgente?
    • Dovrebbero essere entrambi costruiti utilizzando l'automazione o la produzione dovrebbe essere costruita copiando oggetti da un ambiente di test stabile e finalizzato?
    • Automazione per entrambi. NON copiare i dati tra gli ambienti
    • Come gestisci le potenziali differenze tra gli ambienti di test e di produzione negli script di distribuzione?
    • Usa modelli, in modo che tu possa effettivamente produrre diversi set di script per ogni ambiente (es. Riferimenti a sistemi esterni, database collegati, ecc.)
    • Come si verifica che gli script di distribuzione funzioneranno con la stessa efficacia con la produzione come in test?
    • Li testate nell'ambiente di pre-produzione: testate la distribuzione sulla copia esatta dell'ambiente di produzione (database e potenzialmente altri sistemi)
  2. Quali tipi di oggetti dovrebbero essere controllati dalla versione?
    • Solo codice (procedure, pacchetti, trigger, java, ecc.)?
    • Indici?
    • Vincoli?
    • Definizioni delle tabelle?
    • Script di modifica della tabella? (es. ALTER script)
    • Qualunque cosa?
    • Tutto e:
      • Non dimenticare i dati statici (elenchi di ricerca, ecc.), Quindi non è necessario copiare NESSUN dato tra ambienti
      • Mantieni solo la versione corrente degli script del database (controllata dalla versione, ovviamente) e
      • Memorizza gli script ALTER: 1 script BIG (o directory di script denominati like 001_AlterXXX.sql, in modo che eseguendoli in un ordinamento naturale si aggiornerà dalla versione A alla B)
  3. Quali tipi di oggetti non dovrebbero essere controllati dalla versione?
    • Sequenze?
    • Borse di studio?
    • Profili utente?
    • vedere 2. Se i tuoi utenti / ruoli (o nomi utente tecnici) sono diversi tra gli ambienti, puoi comunque creare script utilizzando i modelli (vedi 1.)
  4. Come dovrebbero essere organizzati gli oggetti del database nel repository SCM?
    • Come gestisci cose una tantum come script di conversione o script ALTER?
    • vedere 2.
    • Come gestisci il ritiro degli oggetti dal database?
    • cancellato dal DB, rimosso dal trunk / suggerimento di controllo del codice sorgente
    • Chi dovrebbe essere responsabile della promozione degli oggetti dallo sviluppo al livello di test?
    • pianificazione sviluppo / test / rilascio
    • Come coordini le modifiche di più sviluppatori?
    • prova a NON creare un database separato per ogni sviluppatore. usi il controllo del codice sorgente, giusto? in questo caso gli sviluppatori cambiano il database e registrano gli script. per essere completamente sicuro, ricreare il database dagli script durante la compilazione notturna
    • Come gestisci la ramificazione per gli oggetti di database utilizzati da più sistemi?
    • difficile: cerca di evitare a tutti i costi.
  5. Quali eccezioni, se del caso, possono essere ragionevolmente fatte a questo processo?
    • Problemi di sicurezza?
    • non memorizzare le password per test / prod. puoi consentirlo per lo sviluppo, specialmente se hai ricostruzioni automatiche di DB giornaliere / notturne
    • Dati con problemi di anonimizzazione?
    • Script che non possono essere completamente automatizzati?
    • documentare e archiviare con le informazioni sulla versione / script ALTER
  6. Come puoi rendere il processo resiliente e applicabile?
    • All'errore dello sviluppatore?
    • testato con build giornaliera da zero e confronta i risultati con l'aggiornamento incrementale (dalla versione A alla B utilizzando ALTER). confrontare sia lo schema risultante che i dati statici
    • A problemi ambientali imprevisti?
    • utilizzare il controllo della versione e i backup
    • confronta lo schema del database PROD con quello che pensi che sia, soprattutto prima della distribuzione. SuperDuperCool DBA potrebbe aver corretto un bug che non era mai stato nel tuo sistema di ticket :)
    • Per il ripristino di emergenza?
  7. Come convincere i responsabili delle decisioni che i vantaggi di DB-SCM giustificano davvero il costo?
    • Prove aneddotiche?
    • Ricerca di settore?
    • Consigli di best practice del settore?
    • Ricorsi alle autorità riconosciute?
    • Analisi costi benefici?
    • se sviluppatori e amministratori di database sono d'accordo, non devi convincere nessuno, penso (a meno che tu non abbia bisogno di soldi per acquistare un software come dbGhost per MSSQL)
  8. Chi dovrebbe "possedere" oggetti di database in questo modello?
    • Gli sviluppatori?
    • DBA?
    • Analisti di dati?
    • Più di una?
    • Di solito gli amministratori di database approvano il modello (prima del check-in o dopo come parte della revisione del codice). Sicuramente possiedono oggetti relativi alle prestazioni. Ma in generale il team lo possiede [e il datore di lavoro, ovviamente :)]

Grazie per la tua risposta! Pensi che questi consigli si applichino a tutti i progetti? Conosci strumenti che aiutano a raggiungere questo livello di automazione? Aggiornerò la mia domanda man mano che più persone la soppesano. Inoltre, tieni presente che le mie domande "teaser" non erano intese come un elenco definitivo di preoccupazioni da affrontare, ma più come punto di partenza per la discussione.
LBushkin

Chiaro. Penso che tu abbia sollevato un'ottima domanda. E spero davvero che la domanda riceva abbastanza trazione da permetterti di compilare un fantastico wiki HowTo sull'argomento. ---- dagli strumenti: ho usato dbGhost di Innovartis, che ho menzionato nelle risposte per la gestione del server MSSQL e ha fatto un ottimo lavoro. Probabilmente ci sono altri strumenti per il lavoro, ma dato che lo schema SQL completo non è realmente standard tra i fornitori, non esiste una soluzione all-in-one (per tutti gli SCM e RDMBS).
van

Buona risposta. Suppongo che "cercare elenchi" significhi i dati utilizzati per popolare le caselle <select>? Ciò potrebbe non essere sempre possibile, poiché tali dati potrebbero essere modificati dagli utenti (in qualche modo) durante la produzione. Mantenere i backup ha senso in questo caso. Suggerisci anche di ricreare il database da zero come parte di una build notturna. Non penso che sia una buona idea; può eliminare il lavoro in corso o richiedere la reinstallazione / configurazione di altro software. Infine, suggerirei di creare modalità di test, validatori di dati e altri strumenti invece di costruire da zero per garantire processi resilienti.
Richard Levasseur,

@Richard. Aspetti positivi, ma comunque. Quando leggi "costruire un database da zero", non significa sempre eliminare i dati. Serve a ricostruire lo schema e i dati statici. Se è presente un lavoro in corso (relativo allo schema o ai dati statici) dovrebbe essere nel controllo del codice sorgente, quindi farà parte della build notturna. Se lavori sul ramo con una grande riprogettazione del DB, hai un database separato per questo tipo di sviluppo. E se usi unit-test, non ti affidi allo stato dei dati nel database, ma crei / cancelli come parte di db-unit-test. --- Dati statici spendibili dagli utenti - d'accordo.
furgone

Non sono d'accordo con la ricostruzione dei database ogni notte. Mentre tutto ciò che serve per definire il database, come schemi, trigger, stored procedure e alcuni dati statici "gestiti" dovrebbero essere inseriti in uno script, il materiale effettivo non dovrebbe esserlo. Il contenuto stesso può essere guidato dal compito dello sviluppatore. Abbiamo sviluppatori che lavorano su set di dati per test e sperimentazione. E se arrivassero ogni giorno e il loro stato attuale fosse "ripristinato"? Non bene. Uso i test TestNG che cancellano determinate tabelle e quindi precaricano i dati dei test ogni giorno. Non sembra un candidato per il controllo del codice sorgente.
gregturn

5

Tratto l'SQL come codice sorgente quando possibile

Se riesco a scriverlo in SQL conforme allo standard, generalmente va in un file nel mio controllo del codice sorgente. Il file definirà il più possibile come SP, istruzioni CREATE di tabella.

Includo anche dati fittizi per il test nel controllo del codice sorgente:

  1. proj / sql / setup_db.sql
  2. proj / sql / dummy_data.sql
  3. proj / sql / mssql_specific.sql
  4. proj / sql / mysql_specific.sql

E poi astraggo tutte le mie query SQL in modo da poter creare l'intero progetto per MySQL, Oracle, MSSQL o qualsiasi altra cosa.

L'automazione di compilazione e test utilizza questi script di compilazione poiché sono importanti quanto l'origine dell'app e verifica tutto, dall'integrità ai trigger, alle procedure e alla registrazione.


4

Usiamo l'integrazione continua tramite TeamCity. Ad ogni registrazione al controllo del codice sorgente, il database e tutti i dati di test vengono ricostruiti da zero, quindi il codice, quindi gli unit test vengono eseguiti sul codice. Se stai utilizzando uno strumento di generazione di codice come CodeSmith, può anche essere inserito nel tuo processo di compilazione per generare il tuo livello di accesso ai dati nuovo con ogni build, assicurandoti che tutti i tuoi livelli "corrispondano" e non producano errori a causa di parametri SP non corrispondenti o colonne mancanti.

Ogni build ha la propria raccolta di script SQL che vengono archiviati nella directory $ project \ SQL \ nel controllo del codice sorgente, assegnati un prefisso numerico ed eseguiti in ordine. In questo modo, stiamo esercitando la nostra procedura di distribuzione ad ogni build.

A seconda della tabella di ricerca, la maggior parte dei nostri valori di ricerca sono anche memorizzati negli script ed eseguiti per assicurarci che i dati di configurazione siano ciò che ci aspettiamo, ad esempio, "reason_codes" o "country_codes". In questo modo possiamo apportare una modifica ai dati di ricerca in dev, testarla e quindi "promuoverla" tramite QA e produzione, invece di utilizzare uno strumento per modificare i valori di ricerca in produzione, il che può essere pericoloso per l'uptime.

Creiamo anche una serie di script di "rollback" che annullano le modifiche al nostro database, nel caso in cui una build per la produzione vada male. Puoi testare gli script di rollback eseguendoli, quindi rieseguire gli unit test per la build una versione inferiore alla tua, dopo aver eseguito gli script di distribuzione.


4

+1 per Liquibase : LiquiBase è un open source (LGPL), biblioteca indipendente dal database per il monitoraggio, la gestione e l'applicazione di modifiche al database. Si basa su una semplice premessa: tutte le modifiche al database (struttura e dati) vengono archiviate in modo descrittivo basato su XML e archiviate nel controllo del codice sorgente. Il punto positivo è che le modifiche DML vengono memorizzate semanticamente, non solo diff, in modo da poter tenere traccia dello scopo delle modifiche.

Potrebbe essere combinato con il controllo della versione GIT per una migliore interazione. Configurerò il nostro ambiente dev-prod per provarlo.

Inoltre è possibile utilizzare Maven, i sistemi di compilazione Ant per la creazione di codice di produzione da script.

Il meno è che LiquiBase non si integra negli IDE SQL diffusi e dovresti eseguire le operazioni di base da solo.

In aggiunta a ciò è possibile utilizzare DBUnit per i test DB: questo strumento consente di utilizzare script di generazione dati per testare l'ambiente di produzione con la pulizia successiva.

A PARER MIO:

  1. Memorizza DML nei file in modo da poterli versione.
  2. Automatizza il processo di creazione dello schema dal controllo del codice sorgente.
  3. A scopo di test, lo sviluppatore può utilizzare il DB locale creato dal controllo del codice sorgente tramite il sistema di compilazione + test di carico Dati con script o script DBUnit (dal controllo del codice sorgente).
  4. LiquiBase consente di fornire una "sequenza di esecuzione" di script per rispettare le dipendenze.
  5. Dovrebbe esserci un team DBA che controlla il master brunch con TUTTE le modifiche prima dell'uso in produzione. Voglio dire che controllano trunk / branch da altri DBA prima di eseguire il commit nel trunk MASTER. In modo che il master sia sempre coerente e pronto per la produzione.

Abbiamo affrontato tutti i problemi menzionati con modifiche al codice, unione, riscrittura nel nostro database di produzione della fatturazione. Questo argomento è ottimo per scoprire tutte quelle cose.


3

Facendo "domande teaser" sembri essere più interessato a una discussione che all'opinione di qualcuno sulle risposte finali. La mailing list attiva (> 2500 membri) agileDatabases ha affrontato molte di queste domande ed è, nella mia esperienza, un forum sofisticato e civile per questo tipo di discussione.


Penso che sia improbabile che si possa raggiungere una risposta unica e universalmente concordata. Ma vorrei identificare alcune aree comuni di accordo e forse mettere insieme una raccomandazione ragionevole. Comunque, guarderò sicuramente anche il forum agileDatabases, grazie.
LBushkin

3

Fondamentalmente sono d'accordo con ogni risposta data da van . Per ulteriori informazioni, la mia linea di base per la gestione del database è la serie K. Scott Allen (assolutamente da leggere, IMHO. E anche l'opinione di Jeff sembra).

  • Oggetti di database possono sempre essere ricostruiti da zero con il lancio di un singolo file SQL (che si può chiamare altri file SQL): Create.sql. Ciò può includere l'inserimento di dati statici (elenchi ...).
  • Gli script SQL sono parametrizzati in modo che nessuna informazione dipendente dall'ambiente e / o sensibile venga memorizzata in file semplici.
  • Io uso un file batch personalizzato per il lancio Create.sql: Create.cmd. Il suo obiettivo è principalmente quello di verificare i prerequisiti (strumenti, variabili di ambiente ...) e inviare parametri allo script SQL. Può anche caricare in blocco dati statici da file CSV per problemi di prestazioni.
  • In genere, le credenziali dell'utente di sistema vengono passate come parametro al Create.cmdfile.

IMHO, il caricamento dinamico dei dati dovrebbe richiedere un altro passaggio, a seconda dell'ambiente. Gli sviluppatori vorranno caricare il loro database con dati di prova, spazzatura o nessun dato, mentre dall'altra parte i responsabili della produzione vorranno caricare i dati di produzione. Prenderei in considerazione l'archiviazione dei dati di test anche nel controllo del codice sorgente (per facilitare il test delle unità, ad esempio).

Una volta che la prima versione del database è stata messa in produzione, non sarà necessario solo creare script (principalmente per sviluppatori), ma anche aggiornare gli script (basati sugli stessi principi):

  • Ci deve essere un modo per recuperare la versione dal database (io uso una stored procedure, ma andrebbe bene anche una tabella).
  • Prima di rilasciare una nuova versione, creo un Upgrade.sqlfile (che può chiamare altri) che consente di aggiornare la versione N-1 alla versione N (N è la versione in rilascio). Conservo questo script in una cartella denominata N-1.
  • Ho un file batch che fa l'aggiornamento: Upgrade.cmd. Può recuperare la versione corrente (CV) del database tramite una semplice istruzione SELECT, avviare lo Upgrade.sqlscript archiviato nella CVcartella e ripetere il ciclo finché non viene trovata alcuna cartella. In questo modo, puoi eseguire automaticamente l'aggiornamento da, diciamo, N-3 a N.

I problemi con questo sono:

  • È difficile confrontare automaticamente gli schemi di database, a seconda dei fornitori di database. Ciò può portare a script di aggiornamento incompleti.
  • Ogni modifica all'ambiente di produzione (in genere dagli amministratori di database per l'ottimizzazione delle prestazioni) dovrebbe trovare la sua strada anche nel controllo del codice sorgente. Per essere sicuri di ciò, di solito è possibile registrare ogni modifica al database tramite un trigger. Questo registro viene ripristinato dopo ogni aggiornamento.
  • Più idealmente, tuttavia, le modifiche avviate dal DBA dovrebbero far parte del processo di rilascio / aggiornamento quando possibile.

Per quanto riguarda il tipo di oggetti di database che vuoi avere sotto il controllo del codice sorgente? Bene, direi il più possibile, ma non di più ;-) Se vuoi creare utenti con password, procuragli una password predefinita (login / login, pratico per scopi di unit test) e fai in modo che la modifica della password sia un'operazione manuale . Questo accade spesso con Oracle dove gli schemi sono anche utenti ...


1

Abbiamo il nostro progetto Silverlight con database MSSQL nel controllo della versione Git. Il modo più semplice è assicurarsi di avere un database ridotto (dal punto di vista del contenuto) e fare un dump completo da fe Visual Studio. Quindi puoi fare 'sqlcmd' dal tuo script di build per ricreare il database su ogni macchina di sviluppo.

Per la distribuzione questo non è possibile poiché i database sono troppo grandi: questo è il motivo principale per averli in un database in primo luogo.


1

Credo fermamente che un DB dovrebbe essere parte del controllo del codice sorgente e in larga misura parte del processo di compilazione. Se è nel controllo del codice sorgente, quando scrivo una stored procedure in SQL ho le stesse protezioni di codifica che utilizzo quando scrivo una classe 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 oggetto nel database. Sarebbe una seccatura! Sviluppo nel mio db proprio come farei nel mio progetto di codice. Quindi, quando sono pronto per il check-in, faccio una differenza tra l'ultima versione del mio database e quella corrente 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à presente e il nome descrive cosa viene fatto in questo check in. Lo faccio in questo modo perché come parte del mio processo di compilazione comincio con un nuovo database che viene quindi costruito in modo programmatico utilizzando gli script in questa directory. Ho scritto un'attività NAnt personalizzata che itera attraverso ogni script eseguendone il contenuto sul db nudo. Ovviamente se ho bisogno di alcuni dati da inserire nel db, allora ho anche degli script di inserimento dati. Anche questo ha molti vantaggi. Uno, tutta la mia roba è dotata di versione. Due, ogni build è una nuova build, il che significa che non ci saranno cose subdole che si fanno strada nel mio processo di sviluppo (come i dati sporchi che causano stranezze nel sistema). Tre, quando un nuovo ragazzo viene aggiunto al team di sviluppo, devono semplicemente aggiornarsi e il loro sviluppatore locale viene creato per loro al volo. Quattro, posso eseguire casi di test (non l'ho chiamato "test unitario"!) Sul mio database poiché lo stato del database viene ripristinato ad ogni build (il che significa che posso testare i miei repository senza preoccuparmi di aggiungere dati di test al db).

Questo non è per tutti.

Questo non è per tutti i progetti. Di solito lavoro su progetti di campi verdi che mi consentono questa comodità!


Sono lieto di sapere che stai utilizzando SQL Compare come parte del ciclo di vita di sviluppo del tuo database. Riteniamo di aver migliorato la facilità con cui gli sviluppatori ottengono nuove modifiche. Controlla SQL Source Control. Funziona fianco a fianco con SQL Compare per facilitare la collaborazione degli sviluppatori, oltre a consentire di mantenere il controllo dell'origine degli oggetti dello schema (a condizione che si utilizzi SVN o TFS). red-gate.com/products/sql_source_control/index.htm
David Atkinson

1

Piuttosto che entrare negli argomenti della torre bianca, ecco una soluzione che ha funzionato molto bene per me sui problemi del mondo reale.

La creazione di un database da zero può essere riassunta come la gestione di script SQL.

DBdeploy è uno strumento che controlla lo stato corrente di un database, ad esempio quali script sono stati eseguiti in precedenza su di esso, quali script sono disponibili per essere eseguiti e quindi quali script devono essere eseguiti.

Quindi raccoglierà tutti gli script necessari e li eseguirà. Quindi registra quali script sono stati eseguiti.

Non è lo strumento più bello o il più complesso, ma con un'attenta gestione può funzionare molto bene. È open source e facilmente estensibile. Una volta che l'esecuzione degli script è gestita bene, l'aggiunta di alcuni componenti extra come uno script di shell che controlla gli ultimi script ed esegue dbdeploy su una particolare istanza è facilmente ottenibile.

Vedi una buona introduzione qui:

http://code.google.com/p/dbdeploy/wiki/GettingStarted



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.