Es fiel mir schwer, gute Beispiele für die Verwaltung von Datenbankschemata und -daten zwischen Entwicklungs-, Test- und Produktionsservern zu finden.
Hier ist unser Setup. Jeder Entwickler hat eine virtuelle Maschine, auf der unsere App und die MySQL-Datenbank ausgeführt werden. Es ist ihre persönliche Sandbox, um zu tun, was sie wollen. Derzeit nehmen Entwickler Änderungen am SQL-Schema vor und führen einen Speicherauszug der Datenbank in eine Textdatei durch, die sie in SVN festschreiben.
Wir möchten einen Entwicklungsserver für die kontinuierliche Integration bereitstellen, auf dem immer der neueste festgeschriebene Code ausgeführt wird. Wenn wir das jetzt tun, wird die Datenbank für jeden Build von SVN neu geladen.
Wir haben einen (virtuellen) Testserver, auf dem "Release Candidates" ausgeführt werden. Die Bereitstellung auf dem Testserver ist derzeit ein sehr manueller Vorgang. In der Regel lade ich das neueste SQL aus SVN und optimiere es. Außerdem sind die Daten auf dem Testserver inkonsistent. Sie erhalten die Testdaten, die der letzte Entwickler auf seinem Sandbox-Server festgeschrieben hat.
Wo alles zusammenbricht, ist die Bereitstellung in der Produktion. Da wir die Live-Daten nicht mit Testdaten überschreiben können, müssen alle Schemaänderungen manuell neu erstellt werden. Wenn es eine große Anzahl von Schemaänderungen oder Konvertierungsskripten gab, um die Daten zu manipulieren, kann dies sehr haarig werden.
Wenn das Problem nur das Schema wäre, wäre es ein einfacheres Problem, aber es gibt "Basis" -Daten in der Datenbank, die auch während der Entwicklung aktualisiert werden, wie z. B. Metadaten in Sicherheits- und Berechtigungstabellen.
Dies ist das größte Hindernis, das ich sehe, wenn es um kontinuierliche Integration und One-Step-Builds geht. Wie lösen Sie es?
Eine Folgefrage: Wie verfolgen Sie Datenbankversionen, damit Sie wissen, welche Skripte ausgeführt werden müssen, um eine bestimmte Datenbankinstanz zu aktualisieren? Befindet sich eine Versionstabelle wie Lance unterhalb des Standardverfahrens?
Vielen Dank für den Hinweis auf Tarantino. Ich bin nicht in einer .NET-Umgebung, aber ich fand die DataBaseChangeMangement-Wiki-Seite sehr hilfreich. Besonders diese Powerpoint-Präsentation (.ppt)
Ich werde ein Python-Skript schreiben, das die Namen von *.sql
Skripten in einem bestimmten Verzeichnis mit einer Tabelle in der Datenbank vergleicht und diejenigen, die nicht vorhanden sind, in der Reihenfolge basierend auf einer Ganzzahl ausführt, die den ersten Teil des Dateinamens bildet. Wenn es eine ziemlich einfache Lösung ist, wie ich vermute, werde ich sie hier posten.
Ich habe ein funktionierendes Skript dafür. Die DB wird initialisiert, wenn sie nicht vorhanden ist, und bei Bedarf Upgrade-Skripte ausgeführt. Es gibt auch Schalter zum Löschen einer vorhandenen Datenbank und zum Importieren von Testdaten aus einer Datei. Es sind ungefähr 200 Zeilen, also werde ich es nicht posten (obwohl ich es bei Interesse auf Pastebin legen könnte).
Antworten:
Es gibt ein paar gute Möglichkeiten. Ich würde die Strategie "Backup wiederherstellen" nicht verwenden.
Schreiben Sie alle Ihre Schemaänderungen per Skript und lassen Sie diese Skripte von Ihrem CI-Server in der Datenbank ausführen. Haben Sie eine Versionstabelle, um die aktuelle Datenbankversion zu verfolgen, und führen Sie die Skripte nur aus, wenn sie für eine neuere Version sind.
Verwenden Sie eine Migrationslösung. Diese Lösungen variieren je nach Sprache, aber für .NET verwende ich Migrator.NET. Auf diese Weise können Sie Ihre Datenbank versionieren und zwischen den Versionen auf und ab wechseln. Ihr Schema wird im C # -Code angegeben.
quelle
Ihre Entwickler müssen für jeden Fehler / jede Funktion, an der sie arbeiten, Änderungsskripte (Schema- und Datenänderung) schreiben und nicht nur die gesamte Datenbank in die Quellcodeverwaltung kopieren. Diese Skripte aktualisieren die aktuelle Produktionsdatenbank auf die neue Version in der Entwicklung.
Ihr Erstellungsprozess kann eine Kopie der Produktionsdatenbank in einer geeigneten Umgebung wiederherstellen und alle Skripts von der Quellcodeverwaltung aus ausführen, wodurch die Datenbank auf die aktuelle Version aktualisiert wird. Wir tun dies täglich, um sicherzustellen, dass alle Skripte korrekt ausgeführt werden.
quelle
Schauen Sie sich an, wie Ruby on Rails dies tut.
Erstens gibt es sogenannte Migrationsdateien, die im Grunde das Datenbankschema und die Daten von Version N auf Version N + 1 umwandeln (oder im Falle eines Downgrades von Version N + 1 auf N). Die Datenbank enthält eine Tabelle mit der aktuellen Version.
Testdatenbanken werden vor Unit-Tests immer gelöscht und mit festen Daten aus Dateien gefüllt.
quelle
Das Buch Refactoring Databases: Evolutionary Database Design gibt Ihnen möglicherweise einige Ideen zur Verwaltung der Datenbank. Eine Kurzversion ist auch unter http://martinfowler.com/articles/evodb.html lesbar
In einem PHP + MySQL-Projekt wurde die Datenbankversionsnummer in der Datenbank gespeichert. Wenn das Programm eine Verbindung zur Datenbank herstellt, wird zuerst die Version überprüft. Wenn für das Programm eine andere Version erforderlich ist, wird eine Seite zum Aktualisieren der Datenbank geöffnet. Jedes Upgrade wird im PHP-Code angegeben, wodurch das Datenbankschema geändert und alle vorhandenen Daten migriert werden.
quelle
dev_<<db>> , tst_<<db>> , stg_<<db>> , prd_<<db>>
(Natürlich sollten Sie niemals Datenbanknamen fest codierenquelle
Dies ist etwas, mit dem ich ständig unzufrieden bin - unsere Lösung für dieses Problem. Wir haben mehrere Jahre lang für jede Version ein eigenes Änderungsskript gepflegt. Dieses Skript würde die Deltas aus der letzten Produktionsversion enthalten. Mit jeder Version der Anwendung wird die Versionsnummer erhöht, was ungefähr Folgendes ergibt:
Dies funktionierte gut genug, bis wir zwei Entwicklungslinien pflegten: Trunk / Mainline für Neuentwicklungen und einen Wartungszweig für Fehlerbehebungen, kurzfristige Verbesserungen usw. Es bestand zwangsläufig die Notwendigkeit, Änderungen am Schema in der Verzweigung vorzunehmen. Zu diesem Zeitpunkt hatten wir bereits dbChanges_n + 1.sql im Trunk, sodass wir uns für ein Schema wie das folgende entschieden haben:
Auch dies funktionierte gut genug, bis wir eines Tages 42 Delta-Skripte in der Hauptzeile und 10 in der Filiale sahen. ARGH!
Heutzutage pflegen wir einfach ein Delta-Skript und lassen es von SVN versionieren - dh wir überschreiben das Skript mit jeder Version. Und wir scheuen es, Schemaänderungen in Zweigen vorzunehmen.
Damit bin ich auch nicht zufrieden. Das Konzept der Migrationen von Rails gefällt mir sehr gut. Ich bin ziemlich fasziniert von LiquiBase . Es unterstützt das Konzept der inkrementellen Datenbank-Refactorings. Es ist einen Blick wert und ich werde es bald im Detail betrachten. Hat jemand Erfahrung damit? Ich wäre sehr gespannt auf Ihre Ergebnisse.
quelle
Sie können auch ein Tool wie SQL Compare verwenden, um den Unterschied zwischen verschiedenen Versionen einer Datenbank zu skripten und so schnell zwischen Versionen zu migrieren
quelle
Wir haben ein sehr ähnliches Setup wie das OP.
Entwickler entwickeln in VMs mit privaten DBs.
[Entwickler werden sich bald in privaten Filialen engagieren]
Das Testen wird auf verschiedenen Computern ausgeführt (tatsächlich in VMs, die auf einem Server gehostet werden) [Wird bald vom Hudson CI-Server ausgeführt]
Testen Sie, indem Sie den Referenzspeicherauszug in die Datenbank laden. Wenden Sie die Entwicklerschema-Patches an und wenden Sie dann die Entwicklerdaten-Patches an
Führen Sie dann Unit- und Systemtests durch.
Die Produktion wird als Installateur für Kunden bereitgestellt.
Was wir tun:
Wir nehmen einen Schema-Dump unserer Sandbox-DB. Dann ein SQL-Datendump. Wir unterscheiden das von der vorherigen Basislinie. Dieses Deltapaar soll n-1 auf n aufrüsten.
Wir konfigurieren die Dumps und Deltas.
Um Version N CLEAN zu installieren, führen wir den Dump in eine leere Datenbank aus. Wenden Sie zum Patchen die dazwischen liegenden Patches an.
(Juha erwähnte Rail's Idee, eine Tabelle mit der aktuellen DB-Version zu haben, ist gut und sollte die Installation von Updates weniger schwierig machen.)
Deltas und Dumps müssen vor dem Betatest überprüft werden. Ich kann das nicht umgehen, da Entwickler Testkonten für sich in die Datenbank eingefügt haben.
quelle
Ich fürchte, ich bin mit anderen Postern einverstanden. Entwickler müssen ihre Änderungen skripten.
In vielen Fällen funktioniert eine einfache ALTER TABLE nicht. Sie müssen auch vorhandene Daten ändern. Entwickler müssen sich überlegen, welche Migrationen erforderlich sind, und sicherstellen, dass sie korrekt geschrieben sind (natürlich müssen Sie dies irgendwann sorgfältig testen der Freigabezyklus).
Wenn Sie einen Sinn haben, werden Sie Ihre Entwickler außerdem dazu bringen, Rollbacks für ihre Änderungen zu schreiben, damit sie bei Bedarf zurückgesetzt werden können. Dies sollte ebenfalls getestet werden, um sicherzustellen, dass das Rollback nicht nur fehlerfrei ausgeführt wird, sondern die Datenbank im gleichen Zustand wie zuvor belässt (dies ist nicht immer möglich oder wünschenswert, aber meistens eine gute Regel). .
Wie Sie das an einen CI-Server anschließen, weiß ich nicht. Möglicherweise muss auf Ihrem CI-Server ein bekannter Build-Snapshot vorhanden sein, auf den jede Nacht zurückgegriffen wird und der seitdem alle Änderungen übernimmt. Das ist wahrscheinlich das Beste, sonst bricht ein kaputtes Migrationsskript nicht nur den Build dieser Nacht, sondern alle nachfolgenden.
quelle
Schauen Sie sich die dbdeploy an , es sind bereits Java- und .net-Tools verfügbar. Sie können deren Standards für die SQL- Dateilayouts und die Schemaversionstabelle befolgen und Ihre Python-Version schreiben.
quelle
Wir verwenden die Befehlszeile mysql-diff : Sie gibt einen Unterschied zwischen zwei Datenbankschemata (aus der Live-Datenbank oder dem Skript) als ALTER-Skript aus. mysql-diff wird beim Start der Anwendung ausgeführt. Wenn sich das Schema ändert, wird es dem Entwickler gemeldet. Entwickler müssen ALTERs also nicht manuell schreiben, Schemaaktualisierungen erfolgen halbautomatisch.
quelle
Wenn Sie sich in der .NET-Umgebung befinden, lautet die Lösung Tarantino (archiviert) . All dies (einschließlich der zu installierenden SQL-Skripte) wird in einem NANT-Build behandelt.
quelle
Ich habe ein Tool geschrieben, das (durch Einbinden in Open DBDiff ) Datenbankschemata vergleicht und Ihnen Migrationsskripte vorschlägt. Wenn Sie eine Änderung vornehmen, die Daten löscht oder ändert, wird ein Fehler ausgegeben, aber ein Vorschlag für das Skript bereitgestellt (z. B. wenn eine Spalte im neuen Schema fehlt, wird überprüft, ob die Spalte umbenannt wurde, und xx - generiert erstellt script.sql.suggestion mit einer Umbenennungsanweisung).
http://code.google.com/p/migrationscriptgenerator/ Nur SQL Server Ich fürchte :( Es ist auch ziemlich Alpha, aber es ist SEHR reibungsarm (insbesondere wenn Sie es mit Tarantino oder http://code.google kombinieren .com / p / simplescriptrunner / )
Ich verwende es so, dass ein SQL-Skriptprojekt in Ihrer SLN-Datei vorhanden ist. Sie haben auch lokal eine Datenbank db_next, an der Sie Ihre Änderungen vornehmen (mithilfe von Management Studio oder NHibernate Schema Export oder LinqToSql CreateDatabase oder ähnlichem ). Anschließend führen Sie den migrationscriptgenerator mit den DBs _dev und _next aus, die erstellt werden. die SQL-Update-Skripte für die Migration über.
quelle
Für die Oracle-Datenbank verwenden wir oracle-ddl2svn Tools .
Dieses Tool automatisierte den nächsten Prozess
Änderungen zwischen Instanzen manuell gelöst
quelle