Mechanismen zum Verfolgen von DB-Schemaänderungen [geschlossen]

135

Was sind die besten Methoden zum Verfolgen und / oder Automatisieren von DB-Schemaänderungen? Unser Team verwendet Subversion für die Versionskontrolle und wir konnten einige unserer Aufgaben auf diese Weise automatisieren (Builds auf einen Staging-Server übertragen, getesteten Code auf einem Produktionsserver bereitstellen), aber wir führen Datenbankaktualisierungen immer noch manuell durch. Ich möchte eine Lösung finden oder erstellen, die es uns ermöglicht, effizient auf Servern mit unterschiedlichen Umgebungen zu arbeiten und gleichzeitig Subversion als Backend zu verwenden, über das Code- und DB-Updates auf verschiedene Server übertragen werden.

Viele gängige Softwarepakete enthalten Skripte zur automatischen Aktualisierung, die die DB-Version erkennen und die erforderlichen Änderungen übernehmen. Ist dies der beste Weg, dies auch in größerem Maßstab zu tun (über mehrere Projekte und manchmal mehrere Umgebungen und Sprachen hinweg)? Wenn ja, gibt es einen Code, der den Prozess vereinfacht, oder ist es am besten, nur unsere eigene Lösung zu entwickeln? Hat jemand schon einmal etwas Ähnliches implementiert und es in Subversion-Post-Commit-Hooks integriert, oder ist das eine schlechte Idee?

Während eine Lösung, die mehrere Plattformen unterstützt, vorzuziehen wäre, müssen wir auf jeden Fall den Linux / Apache / MySQL / PHP-Stack unterstützen, da der Großteil unserer Arbeit auf dieser Plattform stattfindet.

pix0r
quelle

Antworten:

56

In der Rails-Welt gibt es das Konzept von Migrationen, Skripten, bei denen Änderungen an der Datenbank in Ruby vorgenommen werden, anstatt eine datenbankspezifische SQL-Variante. Ihr Ruby-Migrationscode wird schließlich in die DDL konvertiert, die für Ihre aktuelle Datenbank spezifisch ist. Dies macht das Wechseln von Datenbankplattformen sehr einfach.

Für jede Änderung, die Sie an der Datenbank vornehmen, schreiben Sie eine neue Migration. Migrationen haben normalerweise zwei Methoden: eine "Auf" -Methode, bei der die Änderungen angewendet werden, und eine "Ab" -Methode, bei der die Änderungen rückgängig gemacht werden. Ein einzelner Befehl bringt die Datenbank auf den neuesten Stand und kann auch verwendet werden, um die Datenbank auf eine bestimmte Version des Schemas zu bringen. In Rails werden Migrationen in einem eigenen Verzeichnis im Projektverzeichnis gespeichert und wie jeder andere Projektcode in die Versionskontrolle eingecheckt.

Dieser Oracle-Leitfaden für Rails-Migrationen behandelt Migrationen recht gut.

Entwickler, die andere Sprachen verwenden, haben sich Migrationen angesehen und ihre eigenen sprachspezifischen Versionen implementiert. Ich kenne Ruckusing , ein PHP-Migrationssystem, das den Migrationen von Rails nachempfunden ist. Es könnte das sein, wonach Sie suchen.

Joey deVilla
quelle
1
Ruckusing FTW - wir haben es an unser DB-System angepasst und sind sehr zufrieden damit.
Piskvor verließ das Gebäude
Es befindet sich jetzt unter github: github.com/ruckus/ruckusing-migrations
50

Wir verwenden etwas Ähnliches wie bcwoord, um unsere Datenbankschemata über 5 verschiedene Installationen (Produktion, Staging und einige Entwicklungsinstallationen) hinweg zu synchronisieren und in der Versionskontrolle zu sichern. Dies funktioniert ziemlich gut. Ich werde ein wenig näher darauf eingehen:


Um die Datenbankstruktur zu synchronisieren, haben wir ein einzelnes Skript, update.php, und eine Reihe von Dateien mit den Nummern 1.sql, 2.sql, 3.sql usw. Das Skript verwendet eine zusätzliche Tabelle, um die aktuelle Versionsnummer von zu speichern Datenbank. Die N.sql-Dateien werden von Hand erstellt, um von Version (N-1) zu Version N der Datenbank zu gelangen.

Sie können verwendet werden, um Tabellen hinzuzufügen, Spalten hinzuzufügen, Daten von einem alten in ein neues Spaltenformat zu migrieren, dann die Spalte zu löschen, "Stamm" -Datenzeilen wie Benutzertypen usw. einzufügen. Grundsätzlich kann alles und mit geeigneten Daten ausgeführt werden Migrationsskripte verlieren nie Daten.

Das Update-Skript funktioniert folgendermaßen:

  • Stellen Sie eine Verbindung zur Datenbank her.
  • Erstellen Sie eine Sicherung der aktuellen Datenbank (weil Sachen wird schief gehen) [mysqldump].
  • Erstellen Sie eine Buchhaltungstabelle (_meta genannt), falls diese nicht vorhanden ist.
  • Lesen Sie die aktuelle VERSION aus der _meta-Tabelle. Nehmen Sie 0 an, wenn nicht gefunden.
  • Führen Sie alle SQL-Dateien, die höher als VERSION nummeriert sind, der Reihe nach aus
  • Wenn eine der Dateien einen Fehler verursacht hat: Führen Sie einen Rollback zur Sicherung durch
  • Andernfalls aktualisieren Sie die Version in der Buchhaltungstabelle auf die höchste ausgeführte SQL-Datei.

Alles geht in die Quellcodeverwaltung, und jede Installation verfügt über ein Skript, das mit einer einzigen Skriptausführung auf die neueste Version aktualisiert werden kann (Aufruf von update.php mit dem richtigen Datenbankkennwort usw.). Wir aktualisieren die Staging- und Produktionsumgebungen von SVN über ein Skript, das das Datenbankaktualisierungsskript automatisch aufruft, sodass eine Codeaktualisierung mit den erforderlichen Datenbankaktualisierungen geliefert wird.

Wir können auch dasselbe Skript verwenden, um die gesamte Datenbank von Grund auf neu zu erstellen. Wir löschen und erstellen die Datenbank einfach neu und führen dann das Skript aus, mit dem die Datenbank vollständig neu gefüllt wird. Wir können das Skript auch verwenden, um eine leere Datenbank für automatisierte Tests zu füllen.


Die Einrichtung dieses Systems dauerte nur wenige Stunden. Es ist konzeptionell einfach und jeder erhält das Versionsnummerierungsschema. Es war von unschätzbarem Wert, das Datenbankdesign voranzutreiben und weiterzuentwickeln, ohne die Änderungen kommunizieren oder manuell ausführen zu müssen auf allen Datenbanken.

Vorsicht beim Einfügen von Abfragen von phpMyAdmin! Diese generierten Abfragen enthalten normalerweise den Datenbanknamen, den Sie definitiv nicht möchten, da dadurch Ihre Skripte beschädigt werden! So etwas wie TABELLE ERSTELLEN mydb. newtable(...) schlägt fehl, wenn die Datenbank auf dem System nicht mydb heißt. Wir haben einen SVN-Hook vor dem Kommentar erstellt, der SQL-Dateien mit der mydbZeichenfolge nicht zulässt. Dies ist ein sicheres Zeichen dafür, dass jemand ohne ordnungsgemäße Überprüfung von phpMyAdmin kopiert / eingefügt hat.

rix0rrr
quelle
Wie sind Sie mit Kollisionen umgegangen? Mehrere Entwickler, die dasselbe Element in der Datenbank ändern, beispielsweise eine gespeicherte Prozedur? Dies kann passieren, wenn Sie gleichzeitig an derselben Niederlassung arbeiten oder zwei Entwicklungslinien in Betrieb sind (zwei Niederlassungen)
Asaf Mesika
Kollisionen waren sehr selten; Das einzige, was wirklich passiert ist, ist, dass zwei Personen versuchen würden, dieselbe N.sql-Datei zu erstellen. Natürlich gewinnt der erste und der zweite muss in die nächsthöhere Zahl umbenennen und es erneut versuchen. Wir hatten die Datenbankversionierung jedoch nicht in einem Zweig.
rix0rrr
12

Mein Team schreibt alle Datenbankänderungen aus und schreibt diese Skripte zusammen mit jeder Version der Anwendung an SVN. Dies ermöglicht inkrementelle Änderungen der Datenbank, ohne dass Daten verloren gehen.

Um von einer Version zur nächsten zu gelangen, müssen Sie nur die Änderungsskripte ausführen, Ihre Datenbank ist auf dem neuesten Stand und Sie haben immer noch alle Ihre Daten. Es ist vielleicht nicht die einfachste Methode, aber es ist definitiv effektiv.

Brandon Wood
quelle
1
Wie schreibt man alle Änderungen aus?
Smith
10

Das Problem hier ist, dass es Entwicklern wirklich einfach ist, ihre eigenen lokalen Änderungen in die Quellcodeverwaltung zu schreiben, um sie mit dem Team zu teilen. Ich bin seit vielen Jahren mit diesem Problem konfrontiert und wurde von der Funktionalität von Visual Studio für Datenbankprofis inspiriert. Wenn Sie ein Open-Source-Tool mit denselben Funktionen wünschen, versuchen Sie Folgendes : http://dbsourcetools.codeplex.com/ Viel Spaß, - Nathan.


quelle
10

Wenn Sie noch nach Lösungen suchen: Wir schlagen ein Tool namens neXtep designer vor. Es ist eine Datenbankentwicklungsumgebung, mit der Sie Ihre gesamte Datenbank unter Versionskontrolle stellen können. Sie arbeiten an einem versionierten Repository, in dem jede Änderung nachverfolgt werden kann.

Wenn Sie ein Update veröffentlichen müssen, können Sie Ihre Komponenten festschreiben, und das Produkt generiert automatisch das SQL-Upgrade-Skript aus der vorherigen Version. Natürlich können Sie diese SQL aus 2 beliebigen Versionen generieren.

Dann haben Sie viele Möglichkeiten: Sie können diese Skripte nehmen und mit Ihrem App-Code in Ihre SVN einfügen, damit sie von Ihrem vorhandenen Mechanismus bereitgestellt werden. Eine andere Möglichkeit besteht darin, den Übermittlungsmechanismus von neXtep zu verwenden: Skripte werden in ein sogenanntes "Übermittlungspaket" (SQL-Skripte + XML-Deskriptor) exportiert. Ein Installationsprogramm kann dieses Paket verstehen und auf einem Zielserver bereitstellen, während es die strkkturale Konsistenz und Abhängigkeit sicherstellt Überprüfen, Registrieren der installierten Version usw.

Das Produkt ist GPL und basiert auf Eclipse, sodass es unter Linux, Mac und Windows ausgeführt werden kann. Derzeit werden auch Oracle, MySQL und Postgresql unterstützt (DB2-Unterstützung ist in Vorbereitung). Schauen Sie sich das Wiki an, in dem Sie detailliertere Informationen finden: http://www.nextep-softwares.com/wiki

Christophe Fondacci
quelle
Sieht interessant aus. Hat es auch eine Kommandozeilenschnittstelle oder ist eine geplant?
Piskvor verließ das Gebäude
8

Scott Ambler produziert eine große Reihe von Artikeln (und hat ein Buch mitverfasst ) über Datenbank-Refactoring mit der Idee, dass Sie im Wesentlichen TDD-Prinzipien und -Praktiken anwenden sollten, um Ihr Schema aufrechtzuerhalten. Sie richten eine Reihe von Struktur- und Seed-Dateneinheitentests für die Datenbank ein. Bevor Sie etwas ändern, ändern / schreiben Sie Tests, um diese Änderung widerzuspiegeln.

Wir machen das schon eine Weile und es scheint zu funktionieren. Wir haben Code geschrieben, um grundlegende Spaltennamen- und Datentypprüfungen in einer Unit-Testing-Suite zu generieren. Wir können diese Tests jederzeit wiederholen, um zu überprüfen, ob die Datenbank im SVN-Checkout mit der Live-Datenbank übereinstimmt, die die Anwendung tatsächlich ausführt.

Wie sich herausstellt, optimieren Entwickler manchmal auch ihre Sandbox-Datenbank und vernachlässigen es, die Schemadatei in SVN zu aktualisieren. Der Code hängt dann von einer Datenbankänderung ab, die nicht eingecheckt wurde. Diese Art von Fehler kann unglaublich schwer zu lokalisieren sein, aber die Testsuite wird ihn sofort erkennen. Dies ist besonders schön, wenn Sie es in einen größeren Plan für die kontinuierliche Integration integriert haben.

Sam McAfee
quelle
7

Speichern Sie Ihr Schema in einer Datei und fügen Sie es der Quellcodeverwaltung hinzu. Dann zeigt Ihnen ein einfacher Diff, was sich geändert hat.

Deadprogrammer
quelle
1
Der Dump muss in SQL sein, wie ein mysqldump, die Dumps von Oracle sind binär.
Osama Al-Maadeed
7
Es gibt auch ein grundlegenderes Problem mit unterschiedlichen Schemata. Wie unterscheidet man ein Spalten-Drop + Add von einem Spalten-Umbenennen? Die Antwort ist einfach: Sie können nicht. Dies ist der Grund, warum Sie die tatsächlichen Schemaänderungsvorgänge aufzeichnen müssen.
PSP
Der Diff zeigt an, dass die eine Spalte verschwunden ist, während die andere angezeigt wurde (es sei denn, sie haben denselben Namen), und meistens reicht dies aus. Das Erstellen von Skripten für jede Schemaänderung ist natürlich ein guter Weg: In Drupal wird dies beispielsweise durch einen speziellen Hook erledigt.
Deadprogrammer
6

K. Scott Allen hat ein oder zwei anständige Artikel zur Schemaversionierung, in denen das inkrementelle Update-Skript / Migrationskonzept verwendet wird, auf das in anderen Antworten hier verwiesen wird. Siehe http://odetocode.com/Blogs/scott/archive/2008/01/31/11710.aspx .

rauben
quelle
5

Es ist ein bisschen Low-Tech, und es gibt vielleicht eine bessere Lösung, aber Sie können Ihr Schema einfach in einem SQL-Skript speichern, das zum Erstellen der Datenbank ausgeführt werden kann. Ich denke, Sie können einen Befehl ausführen, um dieses Skript zu generieren, aber ich kenne den Befehl leider nicht.

Übertragen Sie dann das Skript zusammen mit dem Code, der darauf arbeitet, in die Quellcodeverwaltung. Wenn Sie das Schema zusammen mit dem Code ändern müssen, kann das Skript zusammen mit dem Code eingecheckt werden, für den das geänderte Schema erforderlich ist. Dann zeigen Unterschiede im Skript Unterschiede bei Schemaänderungen an.

Mit diesem Skript können Sie es in DBUnit oder eine Art Build-Skript integrieren, sodass es anscheinend in Ihre bereits automatisierten Prozesse passt.

Mike Stone
quelle
Ja, das ist so ziemlich das, was wir gerade haben. Leider ist dies keine einfache Möglichkeit, vorhandene Datenbanken zu ändern. Das von mysqldump generierte SQL-Skript setzt voraus, dass Sie die Tabelle von Grund auf neu erstellen (oder eine Tabelle überschreiben, falls vorhanden). Wir brauchen etwas High-Techeres, weil es eine Folge von ALTER TABLE-Anweisungen auf die Datenbank anwenden muss, und um dies richtig zu tun, muss es den aktuellen Status der Datenbank kennen.
pix0r
5

Wenn Sie C # verwenden, schauen Sie sich Subsonic an, ein sehr nützliches ORM-Tool, das jedoch auch SQL-Skripte generiert, um Ihr Schema und / oder Ihre Daten neu zu erstellen. Diese Skripte können dann in die Quellcodeverwaltung übernommen werden.

http://subsonicproject.com/

Dan
quelle
Scheint zu diesem Zeitpunkt eine tote URL zu sein.
Mark Schultheiss
5

Ich habe die folgende Datenbankprojektstruktur in Visual Studio für mehrere Projekte verwendet und sie hat ziemlich gut funktioniert:

Datenbank

Skripte ändern

0.PreDeploy.sql

1.SchemaChanges.sql

2.DataChanges.sql

3.Permissions.sql

Skripte erstellen

Sprocs

Funktionen

Ansichten

Unser Build-System aktualisiert dann die Datenbank von einer Version zur nächsten, indem es die Skripte in der folgenden Reihenfolge ausführt:

1.PreDeploy.sql

2.SchemaChanges.sql

Inhalt des Ordners "Skripte erstellen"

2.DataChanges.sql

3.Permissions.sql

Jeder Entwickler überprüft seine Änderungen auf einen bestimmten Fehler / eine bestimmte Funktion, indem er seinen Code an das Ende jeder Datei anfügt. Sobald eine Hauptversion abgeschlossen und in der Quellcodeverwaltung verzweigt ist, wird der Inhalt der SQL-Dateien im Ordner "Skripte ändern" gelöscht.

tbreffni
quelle
5

Wir verwenden eine sehr einfache und dennoch effektive Lösung.

Für Neuinstallationen haben wir eine metadata.sql-Datei im Repository, die das gesamte DB-Schema enthält. Im Erstellungsprozess verwenden wir diese Datei zum Generieren der Datenbank.

Für Updates fügen wir die Updates in der Software fest codiert hinzu. Wir halten es fest codiert, weil wir es nicht mögen, Probleme zu lösen, bevor es wirklich ein Problem ist, und so etwas hat sich bisher nicht als Problem erwiesen.

In unserer Software haben wir also ungefähr Folgendes:

RegisterUpgrade(1, 'ALTER TABLE XX ADD XY CHAR(1) NOT NULL;');

Dieser Code prüft, ob sich die Datenbank in Version 1 befindet (die in einer automatisch erstellten Tabelle gespeichert ist). Wenn sie veraltet ist, wird der Befehl ausgeführt.

Um die Datei metadata.sql im Repository zu aktualisieren, führen wir diese Upgrades lokal aus und extrahieren dann die vollständigen Datenbankmetadaten.

Das einzige, was von Zeit zu Zeit passiert, ist, das Festschreiben der Datei metadata.sql zu vergessen. Dies ist jedoch kein großes Problem, da es einfach ist, den Erstellungsprozess zu testen, und das einzige, was passieren kann, ist, eine neue Installation mit durchzuführen eine veraltete Datenbank und aktualisiert sie bei der ersten Verwendung.

Wir unterstützen auch keine Downgrades, aber es ist beabsichtigt, dass wir bei einem Update die vorherige Version wiederherstellen und das Update reparieren, bevor wir es erneut versuchen.

Fabio Gomes
quelle
4

Ich erstelle Ordner, die nach den Build-Versionen benannt sind, und füge dort Upgrade- und Downgrade-Skripte ein. Beispielsweise könnten Sie die folgenden Ordner haben: 1.0.0, 1.0.1 und 1.0.2. Jedes enthält das Skript, mit dem Sie Ihre Datenbank zwischen verschiedenen Versionen aktualisieren oder herunterstufen können.

Wenn ein Kunde oder Kunde Sie mit einem Problem mit Version 1.0.1 anruft und Sie 1.0.2 verwenden, ist es kein Problem, die Datenbank auf seine Version zurückzusetzen.

Erstellen Sie in Ihrer Datenbank eine Tabelle mit dem Namen "Schema", in der Sie die aktuelle Version der Datenbank eingeben. Dann ist es einfach, ein Programm zu schreiben, mit dem Sie Ihre Datenbank aktualisieren oder herunterstufen können.

Genau wie Joey sagte, wenn Sie sich in einer Rails-Welt befinden, verwenden Sie Migrationen. :) :)

Louis Salin
quelle
3

Für mein aktuelles PHP-Projekt verwenden wir die Idee von Rails-Migrationen und haben ein Migrationsverzeichnis, in dem wir den Dateititel "migration_XX.sql" aufbewahren, wobei XX die Nummer der Migration ist. Derzeit werden diese Dateien von Hand erstellt, wenn Aktualisierungen vorgenommen werden. Ihre Erstellung kann jedoch leicht geändert werden.

Dann haben wir ein Skript namens "Migration_watcher", das, wie wir es in Pre-Alpha sind, derzeit bei jedem Laden der Seite ausgeführt wird und prüft, ob es eine neue Datei "migration_XX.sql" gibt, in der XX größer als die aktuelle Migrationsversion ist. In diesem Fall werden alle migrations_XX.sql-Dateien bis zur größten Anzahl für die Datenbank und voila ausgeführt! Schemaänderungen werden automatisiert.

Wenn Sie die Fähigkeit benötigen, das System zurückzusetzen, wären viele Anpassungen erforderlich, aber es ist einfach und hat bisher für unser relativ kleines Team sehr gut funktioniert.

Eric Scrivner
quelle
3

Ich würde empfehlen, Ant (plattformübergreifend) für die "Scripting" -Seite (da es praktisch mit jeder Datenbank über jdbc kommunizieren kann) und Subversion für das Quell-Repository zu verwenden. Mit Ant können Sie Ihre Datenbank in lokalen Dateien "sichern", bevor Sie Änderungen vornehmen. 1. Sichern Sie das vorhandene Datenbankschema über Ant in der Datei. 2. Versionskontrolle über Ant in das Subversion-Repository. 3. Senden Sie neue SQL-Anweisungen über Ant an die Datenbank

Cruz
quelle
3

Toad for MySQL verfügt über eine Funktion namens Schema Compare, mit der Sie zwei Datenbanken synchronisieren können. Es ist das beste Werkzeug, das ich bisher verwendet habe.

Petah
quelle
3

Mir gefällt die Art und Weise, wie Yii mit Datenbankmigrationen umgeht. Eine Migration ist im Grunde ein implementiertes PHP-Skript CDbMigration. CDbMigrationdefiniert eine upMethode, die die Migrationslogik enthält. Es ist auch möglich, eine downMethode zu implementieren , um die Umkehrung der Migration zu unterstützen. Alternativ safeUpoder safeDownkann verwendet werden, um sicherzustellen, dass die Migration im Kontext einer Transaktion durchgeführt wird.

Das Befehlszeilentool von Yii yiicunterstützt das Erstellen und Ausführen von Migrationen. Migrationen können einzeln oder im Stapel angewendet oder rückgängig gemacht werden. Das Erstellen einer Migration führt zu Code für eine implementierte PHP-Klasse CDbMigration, der anhand eines Zeitstempels und eines vom Benutzer angegebenen Migrationsnamens eindeutig benannt wird. Alle Migrationen, die zuvor auf die Datenbank angewendet wurden, werden in einer Migrationstabelle gespeichert.

Weitere Informationen finden Sie im Artikel zur Datenbankmigration aus dem Handbuch.

Ton van den Heuvel
quelle
2

IMHO-Migrationen haben ein großes Problem:

Ein Upgrade von einer Version auf eine andere funktioniert einwandfrei, aber eine Neuinstallation einer bestimmten Version kann ewig dauern, wenn Sie Hunderte von Tabellen und eine lange Änderungshistorie haben (wie wir).

Das Ausführen der gesamten Deltageschichte seit der Baseline bis zur aktuellen Version (für Hunderte von Kundendatenbanken) kann sehr lange dauern.

Edson Medina
quelle
0

Es gibt ein Befehlszeilen- Tool mysql-diff , das Datenbankschemata vergleicht, wobei das Schema eine Live-Datenbank oder ein SQL-Skript auf der Festplatte sein kann. Es ist gut für die meisten Schemamigrationsaufgaben.

stepancheg
quelle