Mechanismen zum Verfolgen von databaseschemaänderungen

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 (Push-Builds auf einen Staging-Server, Bereitstellung von getestetem Code auf einem Produktionsserver), aber wir führen immer noch databaseupdates manuell durch. Ich möchte eine Lösung finden oder erstellen, die es uns ermöglicht, effizient auf Servern mit unterschiedlichen Umgebungen zu arbeiten, während wir weiterhin Subversion als Backend verwenden, über das Code- und DB-Updates auf verschiedene Server verteilt werden.

Viele populäre Software-Pakete enthalten Auto-Update-Skripte, die die DB-Version erkennen und die notwendigen Änderungen vornehmen. Ist dies der beste Weg, dies auch in einem größeren Maßstab (über mehrere Projekte und manchmal mehrere Umgebungen und Sprachen) zu tun? Wenn ja, gibt es einen vorhandenen Code, der den process vereinfacht, oder ist es am besten, eine eigene Lösung zu erstellen? Hat jemand schon 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 ist, müssen wir auf jeden Fall den Linux / Apache / MySQL / PHP-Stack unterstützen, da der Großteil unserer Arbeit auf dieser Plattform stattfindet.

In der Rails-Welt gibt es das Konzept von Migrationen, Skripten, in denen Änderungen an der database in Ruby statt einer datenbankspezifischen Variante von SQL vorgenommen werden. Ihr Ruby-Migrationscode wird schließlich in die für Ihre aktuelle database spezifische DDL konvertiert. Dies macht den Wechsel von databaseplattformen sehr einfach.

Bei jeder Änderung, die Sie an der database vornehmen, schreiben Sie eine neue Migration. Migrationen haben in der Regel zwei Methoden: eine “up” -Methode, in der die Änderungen angewendet werden, und eine “down” -Methode, in der die Änderungen rückgängig gemacht werden. Ein einzelner Befehl bringt die database auf den neuesten Stand und kann auch verwendet werden, um die database auf eine bestimmte Version des Schemas zu bringen. In Rails werden Migrationen in einem eigenen Verzeichnis im Projektverzeichnis gespeichert und genauso wie jeder andere Projektcode in die Versionskontrolle eingecheckt.

Diese Oracle-Anleitung für Rails-Migrationen deckt Migrationen sehr gut ab.

Entwickler, die andere Sprachen verwenden, haben sich Migrationen angesehen und ihre eigenen sprachspezifischen Versionen implementiert. Ich kenne Ruckusing , ein PHP-Migrations-System, das den Migrationen von Rails nachempfunden ist; Es könnte sein, was du suchst.

Wir verwenden etwas Ähnliches wie bcwoord, um unsere databaseschemata in 5 verschiedenen Installationen (Produktion, Staging und einige Entwicklungsinstallationen) zu synchronisieren und in der Versionskontrolle zu sichern, und es funktioniert ziemlich gut. Ich werde ein wenig ausarbeiten:


Um die databasestruktur zu synchronisieren, haben wir ein einzelnes Skript, update.php, und eine Anzahl von Dateien mit den Nummern 1.sql, 2.sql, 3.sql, etc. Das Skript verwendet eine zusätzliche Tabelle, um die aktuelle Versionsnummer des database. Die N.SQL-Dateien werden von Hand erstellt, um von Version (N-1) zu Version N der database zu wechseln.

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, “Master” -Datenzeilen wie Benutzertypen usw. einzufügen. Grundsätzlich kann es alles und mit geeigneten Daten tun Migrationsskripten verlieren Sie nie Daten.

Das Update-Skript funktioniert so:

  • Stellen Sie eine Verbindung zur database her.
  • Erstellen Sie eine Sicherungskopie der aktuellen database (weil die Dinge schief gehen) [mysqldump].
  • Erstellen Sie eine Buchhaltungstabelle (namens _meta), wenn sie nicht existiert.
  • Lesen Sie die aktuelle VERSION aus der Tabelle _meta. Nehme 0 an, wenn nicht gefunden.
  • Für alle .sql-Dateien, die höher nummeriert sind als VERSION, führen Sie sie der Reihe nach durch
  • Wenn eine der Dateien einen Fehler verursacht hat, führen Sie einen Rollback zur Sicherung durch
  • Aktualisieren Sie andernfalls die Version in der Buchhaltungstabelle mit der höchsten ausgeführten .sql-Datei.

Alles geht in die Quellcodeverwaltung und jede Installation hat ein Skript, um mit einer einzigen Skriptausführung auf die neueste Version zu aktualisieren (Aufruf von update.php mit dem richtigen databasepasswort usw.). Wir SVN aktualisieren Staging- und Produktionsumgebungen über ein Skript, das automatisch das databaseaktualisierungsskript aufruft, sodass ein Code-Update mit den erforderlichen database-Updates geliefert wird.

Wir können auch dasselbe Skript verwenden, um die gesamte database von Grund auf neu zu erstellen. Wir löschen und erstellen die database neu und führen dann das Skript aus, das die database vollständig neu auffüllt. Wir können das Skript auch verwenden, um eine leere database für das automatisierte Testen aufzufüllen.


Es dauerte nur ein paar Stunden, um dieses System einzurichten, es ist konzeptionell einfach und jeder erhält das Versionsnummerierungsschema und es war von unschätzbarem Wert, um das databasedesign weiterzuentwickeln, ohne die Änderungen kommunizieren oder manuell ausführen zu müssen auf allen databaseen.

Vorsicht beim Einfügen von Anfragen von phpMyAdmin! Diese generierten Abfragen enthalten normalerweise den databasenamen, den Sie definitiv nicht haben wollen, da er Ihre Skripte unterbricht! Etwas wie CREATE TABLE mydb . newtable (…) newtable fehl, wenn die database auf dem System nicht myDB heißt. Wir haben einen SVN-Hook vorkommentar erstellt, der sql-Dateien verbietet, die die mydb Zeichenkette enthalten, was ein sicheres Zeichen dafür ist, dass jemand von phpMyAdmin kopiert oder eingefügt wurde, ohne die entsprechende Prüfung mydb .

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

Um von einem Release zum nächsten zu gelangen, müssen Sie nur die Änderungsskripte ausführen, und Ihre database 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.

Das Problem hier macht es wirklich einfach für Entwickler, 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 habe mich von den functionen von Visual Studio für databaseprofis inspirieren lassen. Wenn Sie ein Open-Source-Tool mit den gleichen functionen möchten, versuchen Sie Folgendes : http://dbsourcetools.codeplex.com/ Viel Spaß, – Nathan.

Wenn Sie noch nach Lösungen suchen: Wir schlagen ein Tool namens neXtep Designer vor. Es ist eine databaseentwicklungsumgebung, mit der Sie Ihre gesamte database unter Versionskontrolle stellen können. Sie arbeiten an einem versionsgesteuerten Repository, in dem jede Änderung verfolgt 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 von der vorherigen Version. Natürlich können Sie dieses SQL aus beliebigen 2 Versionen erzeugen.

Dann haben Sie viele Möglichkeiten: Sie können diese Skripte nehmen und sie mit Ihrem App-Code in Ihrem SVN ablegen, so dass sie von Ihrem vorhandenen Mechanismus bereitgestellt werden. Eine weitere Möglichkeit ist die Verwendung des Lieferungsmechanismus von neXtep: Skripte werden in so genannte “delivery packages” (SQL-Skripte + XML-Deskriptor) exportiert, und ein Installer kann dieses Paket verstehen und es auf einem Zielserver bereitstellen, während es die strukurelle Konsistenz und Abhängigkeit gewährleistet prüfen, installierte Version registrieren, etc.

Das Produkt ist GPL und basiert auf Eclipse, also läuft es auf Linux, Mac und Windows. Derzeit unterstützt es auch Oracle, Mysql und Postgresql (DB2-Unterstützung ist auf dem Weg). Schau dir das Wiki an, wo du weitere Informationen findest: http://www.nextep-softwares.com/wiki

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

Scott Ambler erstellt eine großartige Reihe von Artikeln (und Co-Autor eines Buches ) über das Refactoring von databaseen, mit der Idee, dass Sie im Wesentlichen TDD-Prinzipien und -Praktiken anwenden sollten, um Ihr Schema zu pflegen. Sie haben eine Reihe von Struktur- und Seed-Dateneinheitstests für die database eingerichtet. Bevor Sie etwas ändern, modifizieren / 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 Datentypüberprüfungen in einer Einheitentestsuite zu generieren. Wir können diese Tests jederzeit erneut ausführen, um zu überprüfen, ob die database in der SVN-Kasse mit der Live-database übereinstimmt, in der die Anwendung ausgeführt wird.

Es stellt sich heraus, dass Entwickler auch ihre Sandbox-database optimieren und es versäumen, die Schemadatei in SVN zu aktualisieren. Der Code hängt dann von einer DB-Änderung ab, die nicht eingecheckt wurde. Diese Art von Bug kann schwer zu pinnen sein, aber die Testsuite wird sie sofort aufgreifen. Dies ist besonders nützlich, wenn Sie es in einen größeren Continuous Integration-Plan integriert haben.

Es ist ein bisschen Low-Tech, und es könnte eine bessere Lösung da draußen sein, aber Sie könnten Ihr Schema einfach in einem SQL-Skript speichern, das ausgeführt werden kann, um die database zu erstellen. Ich denke, Sie können einen Befehl ausführen, um dieses Skript zu generieren, aber ich kenne den Befehl leider nicht.

Übergeben Sie dann das Skript zusammen mit dem Code, der darauf ausgeführt wird, in die Quellcodeverwaltung. Wenn Sie das Schema zusammen mit dem Code ändern müssen, kann das Skript zusammen mit dem Code, der das geänderte Schema erfordert, eingecheckt werden. Dann zeigen Diffs im Skript Diffs bei Schemaänderungen an.

Mit diesem Skript können Sie es in DBUnit oder eine Art Build-Skript integrieren, so dass es zu Ihren bereits automatisierten processen passt.

Wenn Sie C # verwenden, casting Sie einen Blick auf Subsonic, ein sehr nützliches ORM-Tool, aber es generiert auch SQL-Script, um Ihr Schema und / oder Daten neu zu erstellen. Diese Skripts können dann in die Quellcodeverwaltung eingegeben werden.

http://subsonicproject.com/

K. Scott Allen hat einen oder zwei anständige Artikel zur Schema-Versionierung, die das hier in anderen Antworten referenzierte inkrementelle Update-Skript / Migrationskonzept verwenden; siehe http://odetocode.com/Blogs/scott/archive/2008/01/31/11710.aspx .

Ich habe die folgende databaseprojektstruktur in Visual Studio für mehrere Projekte verwendet und es funktionierte ziemlich gut:

database

Skripte ändern

0.PreDeploy.sql

1.SchemaChanges.sql

2.DataChanges.sql

3.Permissions.sql

Erstellen Sie Skripte

Sprocs

functionen

Ansichten

Unser Buildsystem aktualisiert dann die database von einer Version zur nächsten, indem die Skripts in der folgenden Reihenfolge ausgeführt werden:

1.PreDeploy.sql

2.SchemaChanges.sql

Inhalt des Create Scripts-Ordners

2.DataChanges.sql

3.Permissions.sql

Jeder Entwickler checkt seine Änderungen für einen bestimmten Fehler / Feature ein, indem er seinen Code an das Ende jeder Datei anhängt. Sobald eine Hauptversion in der Quellcodeverwaltung abgeschlossen und verzweigt ist, wird der Inhalt der .sql-Dateien im Ordner “Change Scripts” gelöscht.

Wir verwenden eine sehr einfache, aber dennoch effektive Lösung.

Für neue Installationen haben wir eine metadata.sql-Datei im Repository, die das gesamte DB-Schema enthält, und dann verwenden wir diese Datei im Build-process, um die database zu generieren.

Für Updates fügen wir die Updates in die Hardcoded-Software ein. Wir halten es fest codiert, weil wir Probleme nicht gerne lösen, bevor es wirklich ein Problem ist, und diese Art von Sache erwies sich bisher als kein Problem.

In unserer Software haben wir so etwas:

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

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

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

Das einzige, was immer wieder passiert, ist, die metadata.sql zu vergessen, aber das ist kein großes Problem, da es einfach ist, den Build-process zu testen, und das einzige, was passieren könnte, ist eine neue Installation mit eine veraltete database und aktualisiert es bei der ersten Verwendung.

Wir unterstützen auch keine Downgrades, aber es ist von Entwurf, wenn bei einem Update etwas kaputt geht, haben wir die vorherige Version wiederhergestellt und das Update repariert, bevor wir es erneut versuchen.

Ich erstelle Ordner, die nach den Build-Versionen benannt sind, und setze Upgrade- und Downgrade-Skripte dort ein. Zum Beispiel könnten Sie die folgenden Ordner haben: 1.0.0, 1.0.1 und 1.0.2. Jeder enthält das Skript, mit dem Sie Ihre database zwischen Versionen aktualisieren oder herunterstufen können.

Sollte ein Kunde oder Kunde Sie mit einem Problem mit der Version 1.0.1 in Verbindung setzen und Sie verwenden 1.0.2, ist es kein Problem, die database wieder auf seine Version zu bringen.

Erstellen Sie in Ihrer database eine Tabelle namens “schema”, in die Sie die aktuelle Version der database einfügen. Dann schreiben Sie einfach ein Programm, mit dem Sie Ihre database upgraden oder downgraden können.

Genau wie Joey sagte, wenn du in einer Rails-Welt bist, verwende Migrationen. 🙂

Für mein aktuelles PHP-Projekt verwenden wir die Idee von Rails-Migrationen und wir haben ein Migrationsverzeichnis, in dem wir den Titel “migration_XX.sql” behalten, wobei XX die Nummer der Migration ist. Derzeit werden diese Dateien von Hand erstellt, wenn Aktualisierungen vorgenommen werden, aber ihre Erstellung könnte leicht geändert werden.

Dann haben wir ein Skript namens “Migration_watcher”, das, wie wir in pre-alpha sind, derzeit bei jedem Laden der Seite ausgeführt wird und überprüft, ob es eine neue migration_XX.sql-Datei gibt, in der XX größer ist als die aktuelle Migrationsversion. Wenn dies der Fall ist, werden alle migration_XX.sql-Dateien bis zur höchsten Anzahl gegen die database ausgeführt, und voila! Schemaänderungen sind automatisiert.

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

Ich würde Ant (Cross-Plattform) für die “Scripting” -Seite (da es praktisch mit jeder db da draußen über jdbc sprechen kann) und Subversion für das Quell-Repository empfehlen. Ant wird Ihnen erlauben, Ihre database auf lokale Dateien zu “sichern”, bevor Sie Änderungen vornehmen. 1. Backup existierender DB-Schema in Datei über Ant 2. Versionskontrolle zu Subversion-Repository über Ant 3. Senden Sie neue SQL-statementen an db über Ant

Toad for MySQL hat eine function namens schema compare, mit der Sie 2 databaseen synchronisieren können. Es ist das beste Werkzeug, das ich bisher benutzt habe.

IMHO Migrationen haben ein großes Problem:

Das 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 Historie von Änderungen haben (wie wir es tun).

Die gesamte Historie von Deltas seit der Baseline bis zur aktuellen Version (für hunderte von Kundendatenbanken) kann sehr lange dauern.

Ich mag die Art und Weise, wie Yii databasemigrationen behandelt. Eine Migration ist im Grunde ein PHP-Skript, das CDbMigration implementiert. CDbMigration definiert eine up Methode, die die Migrationslogik enthält. Es ist auch möglich, eine down Methode zu implementieren, um die Umkehrung der Migration zu unterstützen. Alternativ kann safeUp oder safeDown verwendet werden, um sicherzustellen, dass die Migration im Kontext einer Transaktion erfolgt.

Yiis Kommandozeilen-Tool yiic enthält Unterstützung zum Erstellen und Ausführen von Migrationen. Migrationen können entweder einzeln oder in einem Batch angewendet oder rückgängig gemacht werden. Durch die Erstellung einer Migration wird Code für eine PHP-class CDbMigration , die CDbMigration implementiert und basierend auf einem Zeitstempel und einem vom Benutzer angegebenen Migrationsnamen einen eindeutigen Namen CDbMigration . Alle Migrationen, die zuvor auf die database angewendet wurden, werden in einer Migrationstabelle gespeichert.

Weitere Informationen finden Sie im Artikel zur databasemigration im Handbuch.

Versuchen Sie db-deploy – hauptsächlich ein Java-Tool, funktioniert aber auch mit PHP.

Es gibt ein Befehlszeilenprogramm mysql-diff , das databaseschemas vergleicht, wobei Schema eine Live-database oder ein SQL-Skript auf der Festplatte sein kann. Es ist für die meisten Schemamigrationsaufgaben geeignet.