Wie verwalten Sie Datenbanken in Entwicklung, Test und Produktion?

171

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 *.sqlSkripten 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).

Matt Miller
quelle
"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 von bildet der Dateiname. Wenn es eine ziemlich einfache Lösung ist, wie ich vermute, dann werde ich sie hier posten. " Klingt so, als würden Sie Flyway implementieren.
Masterxilo

Antworten:

53

Es gibt ein paar gute Möglichkeiten. Ich würde die Strategie "Backup wiederherstellen" nicht verwenden.

  1. 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.

  2. 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.

Lance Fisher
quelle
28

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.

tbreffni
quelle
13

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.

Juha Syrjälä
quelle
10

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.

Esko Luontola
quelle
5
  • Benennen Sie Ihre Datenbanken wie folgt: dev_<<db>> , tst_<<db>> , stg_<<db>> , prd_<<db>>(Natürlich sollten Sie niemals Datenbanknamen fest codieren
  • Auf diese Weise können Sie sogar die verschiedenen DB-Typen auf demselben physischen Server bereitstellen (das empfehle ich nicht, aber Sie müssen möglicherweise ... wenn die Ressourcen knapp sind).
  • Stellen Sie sicher, dass Sie Daten automatisch zwischen diesen verschieben können
  • Trennen Sie die Datenbankerstellungsskripte von der Grundgesamtheit = Es sollte immer möglich sein, die Datenbank von Grund auf neu zu erstellen und zu füllen (aus der alten Datenbankversion oder einer externen Datenquelle)
  • Verwenden Sie keine Hardcode-Verbindungszeichenfolgen im Code (auch nicht in den Konfigurationsdateien). Verwenden Sie in den Konfigurationsdateien Verbindungszeichenfolgenvorlagen, die Sie dynamisch ausfüllen. Jede Neukonfiguration der Anwendungsschicht, die neu kompiliert werden muss, ist SCHLECHT
  • Verwenden Sie die Datenbankversionierung und die Versionierung von Datenbankobjekten - wenn Sie es sich leisten können, verwenden Sie fertige Produkte, wenn Sie nicht selbst etwas entwickeln
  • Verfolgen Sie jede DDL-Änderung und speichern Sie sie in einer Verlaufstabelle ( Beispiel hier ).
  • TÄGLICHE Backups! Testen Sie, wie schnell Sie etwas wiederherstellen können, das aus einer Sicherung verloren gegangen ist (verwenden Sie automatische Wiederherstellungsskripte
  • Sogar Ihre DEV-Datenbank und der PROD haben genau das gleiche Erstellungsskript, bei dem Sie Probleme mit den Daten haben. Ermöglichen Sie Entwicklern daher, die genaue Kopie von prod zu erstellen und damit zu spielen (ich weiß, dass ich für dieses eine Minuspunkte erhalten werde, aber ändern Sie das Denkweise und Geschäftsprozess kosten Sie viel weniger, wenn Scheiße auf den Fan trifft - zwingen Sie die Programmierer also, legal zu zeichnen, was auch immer es macht, aber stellen Sie sicher, dass dies der Fall ist
Yordan Georgiev
quelle
Der letzte Punkt ist in der Tat die Stimmung. Wenn es notwendig ist, zeigt es, dass die Definition des Projekts fehlerhaft ist. Entwicklung muss vor der Produktion führen. Wenn Produktionsdaten Nebenwirkungen hervorrufen, treten größere Probleme auf. Reinigen Sie die Produktionsdaten. Klären Sie auch den letzten Schritt mit dem Datenschutzbeauftragten. Wenn - wie Sie meinen - Grund dafür besteht, dass sich Live-Daten auf Entwicklungssystemen befinden müssen, prüfen Sie, ob dies rechtlich anwendbar ist. Auch eine exakte Kopie der Produktionsdaten verlangsamt die Entwicklung und Integration erheblich. Betrachten Sie einen kostengünstigeren Prozess, wenn Sie sich einen solchen Luxus nicht leisten können.
hakre
Die Sache ist, dass es während der Entwicklung einfach nicht einmal möglich ist, sich alle Eckfälle im Kontrollfluss und die Schwankungen in der Datenqualität vorzustellen, die in der Produktion auftreten werden. Wenn Sie sich in einem so großen Unternehmen befinden, müssen rechtliche Probleme implementiert werden, als eine Art Datenverschlüsselungs- und / oder Maskierungslösung zu implementieren, die zusätzliche Komplexitätsebene hinzufügt, aber dennoch die Datenqualitätsaspekte beibehält, die den Fehler verursacht haben in erster Linie sowieso ...
Yordan Georgiev
4

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:

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

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:

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

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.

Matt Stine
quelle
4

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

Rad
quelle
3

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.

Tim Williscroft
quelle
3

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.

MarkR
quelle
1

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.

Dave Marshall
quelle
1

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.

stepancheg
quelle
0

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.

mcintyre321
quelle
0

Für die Oracle-Datenbank verwenden wir oracle-ddl2svn Tools .

Dieses Tool automatisierte den nächsten Prozess

  1. Für jedes DB-Schema erhalten Sie Schema-DDLs
  2. stelle es unter version contol

Änderungen zwischen Instanzen manuell gelöst

Popalka
quelle