Wie kann ich eine database unter git (Versionskontrolle) setzen?

Ich mache eine Web-App, und ich muss einen Zweig für einige wichtige Änderungen machen, die Sache ist, diese Änderungen erfordern Änderungen an der database-Schema, so würde ich gerne die gesamte database unter Git auch.

Wie mache ich das? Gibt es einen bestimmten Ordner, den ich unter einem Git Repository aufbewahren kann? Woher weiß ich welchen? Wie kann ich sicher sein, dass ich den richtigen Ordner anlege?

Ich muss mir sicher sein, denn diese Änderungen sind nicht abwärtskompatibel. Ich kann es mir nicht leisten, etwas zu vermasseln.

Die database ist in meinem Fall PostgreSQL

Bearbeiten:

Jemand schlug vor, Backups zu erstellen und die Backup-Datei anstelle der database der Versionskontrolle zu unterstellen. Um ehrlich zu sein finde ich das wirklich schwer zu schlucken.

Es muss einen besseren Weg geben.

Aktualisieren:

OK, also gibt es keinen besseren Weg, aber ich bin immer noch nicht ganz überzeugt, also werde ich die Frage ein wenig ändern:

Ich möchte die gesamte database unter Versionskontrolle setzen, welche database-Engine kann ich verwenden, so dass ich die tatsächliche database unter Versionskontrolle statt seiner Dump setzen kann?

Wäre sqlite git-freundlich?

Da dies nur die Entwicklungsumgebung ist, kann ich die gewünschte database auswählen.

Edit2:

Was ich wirklich will, ist nicht, meine Entwicklungsgeschichte zu verfolgen, sondern in der Lage zu sein, von meinem Zweig “neue radikale Änderungen” auf den “aktuellen stabilen Zweig” umzusteigen und zum Beispiel einige Bugs / Probleme usw. mit dem aktuellen zu beheben stabiler Zweig. So, dass, wenn ich Zweige vertausche, die database automatisch mit dem Zweig kompatibel ist, in dem ich mich gerade befinde. Die tatsächlichen Daten interessieren mich nicht wirklich.

Nehmen Sie stattdessen einen database-Dump und eine Versionskontrolle vor. Auf diese Weise ist es eine flache Textdatei.

Persönlich schlage ich vor, dass Sie sowohl einen Datenabzug als auch einen Schemadump aufbewahren. Auf diese Weise wird es mit diff sehr einfach zu sehen, was sich im Schema von Revision zu Revision geändert hat.

Wenn Sie große Änderungen vornehmen, sollten Sie eine sekundäre database haben, in der Sie das neue Schema ändern und nicht die alte ändern, da Sie, wie Sie sagten, eine Verzweigung erstellen.

In Refactoring Databases ( http://datataferefactoring.com/ ) finden Sie eine Reihe guter Techniken zur Verwaltung Ihrer database in Verbindung mit Codeänderungen.

Es genügt zu sagen, dass Sie die falschen Fragen stellen. Anstatt Ihre database in git zu setzen, sollten Sie Ihre Änderungen in kleine überprüfbare Schritte zerlegen, damit Sie Schemaänderungen problemlos migrieren / zurücksetzen können.

Wenn Sie vollständige Wiederherstellbarkeit wünschen, sollten Sie in Erwägung ziehen, Ihre PostgreSQL-Logs zu archivieren und PITR (Point-in-Time-Recovery) zu verwenden, um Transaktionen in bestimmten, bekannten, guten Zuständen abzuspielen.

Ich fange an, an eine wirklich einfache Lösung zu denken, weiß nicht, warum ich vorher nicht daran gedacht habe !!

  • Duplizieren Sie die database (sowohl das Schema als auch die Daten).
  • Ändern Sie in der Verzweigung für die neuen Hauptänderungen einfach die Projektkonfiguration, um die neue doppelte database zu verwenden.

Auf diese Weise kann ich die Zweige wechseln, ohne sich um databaseschemaänderungen kümmern zu müssen.

BEARBEITEN:

Mit Duplikat meine ich eine andere database mit einem anderen Namen (wie my_db_2 ); keine Müllhalde machen oder so etwas.

Anstatt Ihre DB manuell zu speichern und sie in git zu speichern, verwenden Sie Offscale DataGrove .

DataGrove ist im Grunde eine DB-Versionskontrolle – es verfolgt Änderungen an der gesamten database (Schema UND Daten) und erlaubt es Ihnen, Versionen in das Repository zu taggen. Sie können es zusammen mit git verwenden und jedes Mal, wenn Sie den Code einchecken, eine Version markieren und den richtigen DB-Status laden, wenn Sie Code abrufen.

Speziell zu “Edit 2” – mit DataGrove können Sie einfach zwei Zweige der DB haben, einen für jeden Ihrer Code-Zweige. Wenn Sie einen bestimmten Zweig des Codes laden, erstellt DataGrove automatisch den gesamten DB-Status mit allen Daten für diese Version / Zweigstelle neu. Das bedeutet, dass Sie mit einem einzigen, einfachen Befehl zwischen Entwicklungszweigen wechseln können.

Verwenden Sie etwas wie LiquiBase, damit Sie die Versionskontrolle Ihrer Liquibase-Dateien behalten können. Sie können Änderungen nur für die Produktion markieren und Ihre database für die Produktion oder die Entwicklung auf dem neuesten Stand halten (oder nach dem von Ihnen gewünschten Schema).

Es gibt ein Tool namens Klonio , dessen Beta-Version verfügbar ist. Es unterstützt MongoDB und MySQL ab sofort.

Natürlich hat es Git-Integration und Sie können entweder Ihr Schema allein oder sogar die enthaltenen Daten aufnehmen.

Es gibt ein großartiges Projekt mit der Bezeichnung “Migrations in Doctrine”, das nur für diesen Zweck gebaut wurde.

Es ist immer noch im Alpha-Zustand und für PHP gebaut.

http://docs.doctrine-project.org/projects/doctrine-migrations/en/latest/index.html

Sehen Sie sich RedGate SQL Source Control an.

http://www.red-gate.com/products/sql-development/sql-source-control/

Dieses Tool ist ein SQL Server Management Studio-Snap-In, mit dem Sie Ihre database unter Quellcodeverwaltung mit Git platzieren können.

Es ist ein bisschen teuer bei $ 495 pro Benutzer, aber es gibt eine 28-Tage-Testversion zur Verfügung.

HINWEIS Ich bin in keiner Weise mit RedGate verbunden.

Ich bin auf diese Frage gestoßen, da ich ein ähnliches Problem habe, bei dem etwas, das einer DB-basierten Verzeichnisstruktur nahekommt, “Dateien” speichert und ich git brauche, um es zu verwalten. Es wird über eine Cloud verteilt, wobei die Replikation verwendet wird, daher wird der Zugang über MySQL erfolgen.

Der core der obigen Antworten scheint in ähnlicher Weise eine alternative Lösung für das gestellte Problem vorzuschlagen, die den Punkt vermisst, Git zu benutzen, um etwas in einer database zu verwalten, also werde ich versuchen, diese Frage zu beantworten.

Git ist ein System, das im Wesentlichen eine database von Deltas (Differenzen) speichert, die wieder zusammengesetzt werden können, um einen Kontext zu reproduzieren. Die normale Verwendung von git setzt voraus, dass der Kontext ein Dateisystem ist, und diese Deltas Diffs in diesem Dateisystem sind, aber wirklich alles git ist, ist eine hierarchische database von Deltas (hierarchisch, weil in den meisten Fällen jedes Delta ein Commit mit mindestens 1 ist Eltern, in einem Baum angeordnet).

Solange Sie ein Delta erzeugen können, kann git es theoretisch speichern. Das Problem ist normalerweise, dass git den Kontext erwartet, in dem Delta generiert wird, um ein Dateisystem zu sein, und ähnlich, wenn Sie einen Punkt in der Git-Hierarchie auschecken, erwartet es ein Dateisystem zu erzeugen.

Wenn Sie Änderungen in einer database verwalten wollen, haben Sie zwei diskrete Probleme, und ich würde sie getrennt behandeln (wenn ich Sie wäre). Der erste ist ein Schema, der zweite sind Daten (obwohl Sie in Ihrer Frage nicht angeben, um welche Daten es sich handelt). Ein Problem, das ich in der Vergangenheit hatte, war eine Dev und Prod database, wo Dev inkrementelle Änderungen am Schema vornehmen konnte, und diese Änderungen mussten in CVS dokumentiert und propagiert werden, um zu leben, zusammen mit Ergänzungen zu einem von mehreren ‘statischen’ Tabellen. Wir haben das getan, indem wir eine dritte database namens Cruise hatten, die nur die statischen Daten enthielt. An jedem Punkt konnte das Schema von Dev und Cruise verglichen werden, und wir hatten ein Skript, um das diff dieser 2 Dateien zu nehmen und eine SQL-Datei zu erzeugen, die ALTER-statementen enthielt, um es anzuwenden. In ähnlicher Weise könnten alle neuen Daten in eine SQL-Datei mit INSERT-Befehlen umgewandelt werden. Solange Felder und Tabellen nur hinzugefügt und niemals gelöscht werden, könnte der process die SQL-statementen zum Anwenden des Deltas automatisch generieren.

Der Mechanismus, mit dem git Deltas erzeugt, ist diff und der Mechanismus, mit dem es 1 oder mehr Deltas mit einer Datei kombiniert, wird merge . Wenn Sie eine Methode zum Diffamen und Zusammenführen aus einem anderen Kontext entwickeln können, sollte git funktionieren, aber wie bereits erwähnt, bevorzugen Sie vielleicht ein Tool, das das für Sie erledigt. Mein erster Gedanke, dies zu lösen, ist diese https://git-scm.com/book/en/v2/Customing-Git-Git-Configuration#External-Merge-and-Diff-Tools, die beschreibt, wie git’s internes diff ersetzt werden kann Zusammenführungswerkzeug. Ich werde diese Antwort aktualisieren, da ich eine bessere Lösung für das Problem gefunden habe, aber in meinem Fall erwarte ich, dass ich Datenänderungen nur verwalten muss – insofern, als sich ein DB-basierter Dateispeicher ändern könnte, also meine Lösung ist vielleicht nicht genau das, was du brauchst.

Sie können es nicht ohne Atomizität tun, und Sie können Atomizität nicht erhalten, ohne entweder pg_dump oder ein Schnappschuss-Dateisystem zu verwenden.

Meine postgres-Instanz ist auf zfs, die ich gelegentlich Momentaufnahme. Es ist ungefähr sofort und konsistent.

Was Sie im Geiste wollen, ist vielleicht etwas wie Post-Facto , das Versionen einer database in einer database speichert. Überprüfen Sie diese Präsentation .

Das Projekt ging anscheinend nie wirklich irgendwo hin, also wird es dir wahrscheinlich nicht sofort helfen, aber es ist ein interessantes Konzept. Ich befürchte, dass es sehr schwierig sein würde, dies richtig zu machen, denn sogar Version 1 müsste alle Details richtig machen, damit die Leute ihrer Arbeit vertrauen können.

Ich habe ein Tool für sqlite veröffentlicht, das genau das tut, wonach du verlangst. Es verwendet einen benutzerdefinierten Diff-Treiber, der das sqlite-Projekttool ‘sqldiff’, UUIDs als Primärschlüssel nutzt und die sqlite rowid verlässt. Es ist immer noch in Alpha, so dass Feedback geschätzt wird.

Postgres und MySQL sind kniffliger, da die Binärdaten in mehreren Dateien gespeichert sind und möglicherweise nicht einmal gültig sind, wenn Sie Snapshots erstellen konnten.

https://github.com/cannadayr/git-sqlite

Ich möchte etwas Ähnliches machen, meine databaseänderungen zu meinem Versionskontrollsystem hinzufügen.

Ich werde die Ideen in diesem Beitrag von Vladimir Khorikov “Best Practices zur databaseversionierung” folgen. Zusammenfassend werde ich

  • speichert sowohl sein Schema als auch die Referenzdaten in einem Quellcodeverwaltungssystem.
  • Für jede Änderung erstellen wir ein separates SQL-Skript mit den Änderungen

Falls es hilft!

Ich denke, X-Istce ist auf dem richtigen Weg, aber es gibt noch ein paar Verbesserungen, die Sie an dieser Strategie vornehmen können. Erste Benutzung:

 $pg_dump --schema ... 

um die Tabellen, Sequenzen usw. abzulegen und diese Datei unter Versionskontrolle zu stellen. Sie verwenden dies, um die Kompatibilitätsänderungen zwischen Ihren Zweigen zu trennen.

Als nächstes führen Sie einen Daten-Dump für den Satz von Tabellen durch, die die Konfiguration enthalten, die für den Betrieb Ihrer Anwendung benötigt wird (sollte Benutzerdaten überspringen können), wie Formular-Standardwerte und andere Daten, die nicht von Benutzern geändert werden können. Sie können dies selektiv tun mit:

 $pg_dump --table=..  --exclude-table=.. 

Dies ist eine gute Idee, weil das Repo sehr klobig werden kann, wenn Ihre database 100 MB + bei einem vollständigen Datenabzug erreicht. Eine bessere Idee ist es, ein Minimum an Daten zu sichern, die Sie zum Testen Ihrer App benötigen. Wenn Ihre Standarddaten jedoch sehr groß sind, kann dies dennoch Probleme verursachen.

Wenn Sie unbedingt vollständige Backups in das Repo-Verzeichnis einfügen müssen, sollten Sie dies in einem Zweig außerhalb Ihres Quellverzeichnisbaums tun. Ein externes Backup-System mit einem Verweis auf die passende SVN rev ist dafür wahrscheinlich am besten.

Außerdem schlage ich vor, Textformat-Dumps über Binärdateien für Revisionszwecke (zumindest für das Schema) zu verwenden, da diese leichter zu unterscheiden sind. Sie können diese immer komprimieren, um vor dem Einchecken Platz zu sparen.

Sehen Sie sich schließlich die Postgres-Backup-Dokumentation an, falls Sie dies noch nicht getan haben. Die Art und Weise, wie Sie die Sicherung der ‘database’ kommentieren und nicht ein Speicherauszug, lässt mich fragen, ob Sie an Dateisystem-basierte Backups denken (siehe Abschnitt 23.2 für Vorbehalte).

Diese Frage ist ziemlich beantwortet, aber ich möchte die Antwort von X-Isstence und Dana the Sane mit einem kleinen Vorschlag ergänzen.

Wenn Sie eine Versionskontrolle mit einem gewissen Grad an Granularität benötigen, sagen Sie täglich, können Sie den Text-Dump der Tabellen und des Schemas mit einem Tool wie rdiff-backup verbinden, das inkrementelle Backups erstellt. Der Vorteil besteht darin, dass Sie nicht die Snapshots der täglichen Backups speichern, sondern lediglich die Unterschiede zum vorherigen Tag speichern.

Damit haben Sie den Vorteil der Revisionskontrolle und verschwenden nicht zu viel Platz.

In jedem Fall ist die Verwendung von Git direkt auf großen flachen Dateien, die sich sehr häufig ändern, keine gute Lösung. Wenn Ihre database zu groß wird, wird Git einige Probleme haben, die Dateien zu verwalten.

Ich würde neXtep für die Version empfehlen, die die database steuert, es hat eine gute Reihe von Dokumentation und Foren, die erklärt, wie man installiert und die Fehler aufgetreten ist. Ich habe es für PostgreSQL 9.1 und 9.3 getestet, ich konnte es für 9.1 arbeiten, aber für 9.3 scheint es nicht zu funktionieren.

Was ich in meinen persönlichen Projekten mache, ist, dass ich meine gesamte database in Dropbox ablege und dann auf MAMP, WAMP-Workflow zeige, um es direkt von dort zu verwenden. Auf diese Weise ist die database immer aktuell, wo immer ich etwas entwickeln muss. Aber das ist nur für Entwickler! Live-Sites verwendet dafür natürlich einen eigenen Server! 🙂

Das Speichern jeder Ebene von databaseänderungen unter der Versionsverwaltung von git sieht so aus, als würde man die gesamte database mit jedem Commit pushen und bei jedem Pull die gesamte database wiederherstellen . Wenn Ihre database so anfällig für wichtige Änderungen ist und Sie es sich nicht leisten können, sie zu verlieren, können Sie einfach Ihre pre_commit- und post_merge- Hooks aktualisieren . Ich habe dasselbe mit einem meiner Projekte gemacht und Sie können die Richtungen hier finden .

So mach ich es:

Da Sie sich frei über den DB-Typ entscheiden, verwenden Sie eine dateibasierte DB wie zB Firebird.

Erstellen Sie eine Vorlagen-DB, die das Schema enthält, das zu Ihrer tatsächlichen Zweigstelle passt, und speichern Sie sie in Ihrem Repository.

Erstellen Sie beim Ausführen Ihrer Anwendung programmatisch eine Kopie Ihrer Vorlagen-DB, speichern Sie sie woanders und arbeiten Sie nur mit dieser Kopie.

Auf diese Weise können Sie Ihr DB-Schema unter Versionskontrolle ohne die Daten setzen. Und wenn Sie Ihr Schema ändern, müssen Sie nur die Vorlagen-DB ändern

Wir haben eine Social-Website mit einer Standard-LAMP-Konfiguration betrieben. Wir hatten einen Live-Server, einen Testserver und einen Entwicklungsserver sowie die lokalen Entwicklermaschinen. Alle wurden mit GIT verwaltet.

Auf jeder Maschine befanden sich die PHP-Dateien, aber auch der MySQL-Dienst und ein Ordner mit Bildern, die Benutzer hochladen würden. Der Live-Server wuchs auf 100K (!) Wiederkehrende Nutzer, der Dump lag bei ca. 2GB (!), Der Image-Ordner bei ca. 50GB (!). Zu der Zeit, als ich ging, erreichte unser Server die Grenze seiner CPU, Ram, und vor allem, die gleichzeitige Netzverbindungslimits (Wir kompilierten sogar unsere eigene Version des Netzwerkkartentreibers, um den Server ‘lol’ zu maximieren). Wir konnten ( und sollten nicht von Ihrer Website ausgehen ) 2 GB Daten und 50 GB Bilder in GIT speichern.

Um all dies unter GIT einfach zu verwalten, würden wir die Binärordner (die Ordner, die die Bilder enthalten) ignorieren, indem wir diese Ordnerpfade in .gitignore einfügen. Wir hatten auch einen Ordner namens SQL außerhalb des Apache Documentroot-Pfades. In diesem SQL-Ordner würden wir unsere SQL-Dateien von den Entwicklern in inkrementeller Nummerierung (001.florianm.sql, 001.johns.sql, 002.florianm.sql usw.) ablegen. Diese SQL-Dateien wurden ebenfalls von GIT verwaltet. Die erste SQL-Datei würde in der Tat eine große Menge von DB-Schema enthalten. Wir fügen keine Benutzerdaten in GIT hinzu (z. B. die Datensätze der Benutzertabelle oder der Kommentartabelle), aber Daten wie Konfigurationen oder Topologie oder andere standortspezifische Daten wurden in den SQL-Dateien (und somit von GIT) gepflegt. Meist sind es die Entwickler (die den Code am besten kennen), die bestimmen, was und was nicht von GIT in Bezug auf SQL-Schema und Daten gepflegt wird.

Bei der Veröffentlichung meldet sich der Administrator am Dev-Server an, führt den Live-Zweig mit allen Entwicklern zusammen und benötigte Verzweigungen auf dem Dev-Rechner zu einem Update-Zweig und schob ihn zum Test-Server. Auf dem Testserver prüft er, ob der Update-process für den Live-Server noch gültig ist, und zeigt in kurzer Folge den gesamten Verkehr in Apache an eine Platzhalter-Site an, erstellt einen DB-Dump und verweist das Arbeitsverzeichnis von “live” auf “update” ‘, führt alle neuen SQL-Dateien in mysql aus und richtet den Datenverkehr wieder auf die richtige Site um. Wenn alle Beteiligten nach der Prüfung des Testservers zugestimmt haben, hat der Administrator das Gleiche von Testserver zu Live-Server getan. Anschließend fusioniert er den Live-Zweig auf dem Produktionsserver mit dem Master-Zweig über alle Server und refasst alle Live-Zweige neu. Die Entwickler waren selbst dafür verantwortlich, ihre Filialen neu zu gestalten, aber sie wissen im Allgemeinen, was sie tun.

Wenn es Probleme auf dem Testserver gab, z. Die Zusammenführungen hatten zu viele Konflikte, dann wurde der Code zurückgesetzt (der Arbeitszweig wurde wieder auf “live” gesetzt) ​​und die SQL-Dateien wurden nie ausgeführt. In dem Moment, in dem die SQL-Dateien ausgeführt wurden, wurde dies zu der Zeit als nicht umkehrbare Aktion betrachtet. Wenn die SQL-Dateien nicht richtig funktionierten, wurde die database mit dem Dump wiederhergestellt (und die Entwickler sagten, dass sie ungeprüfte SQL-Dateien zur Verfügung stellen sollten).

Heute unterhalten wir sowohl einen sql-up- als auch einen sql-down-Ordner mit entsprechenden Dateinamen, wobei die Entwickler testen müssen, ob die beiden sql-upgrade-Dateien gleichermaßen herabgestuft werden können. Dies könnte letztendlich mit einem Bash-Skript ausgeführt werden, aber es ist eine gute Idee, wenn die menschlichen Augen den Upgrade-process überwachen.

Es ist nicht großartig, aber es ist überschaubar. Ich hoffe, dies gibt einen Einblick in eine praxisnahe, relativ hoch verfügbare Website. Sei es ein bisschen veraltet, aber immer noch gefolgt.

Verwenden Sie ein Tool wie iBatis Migrations ( Handbuch , kurzes Tutorialvideo ), mit dem Sie die Änderungen, die Sie während des gesamten Lebenszyklus eines Projekts an einer database vornehmen, versionsgesteuert steuern können, anstatt die database selbst zu verwenden.

Auf diese Weise können Sie einzelne Änderungen selektiv auf verschiedene Umgebungen anwenden, ein Änderungsprotokoll mit den Änderungen in den jeweiligen Umgebungen erstellen, Skripts erstellen, um die Änderungen A bis N anzuwenden, Rollback-Änderungen usw.

Ich möchte die gesamte database unter Versionskontrolle setzen, welche database-Engine kann ich verwenden, so dass ich die tatsächliche database unter Versionskontrolle statt seiner Dump setzen kann?

Dies ist nicht abhängig von der database-Engine. Von Microsoft SQL Server gibt es viele Versionskontrollprogramme. Ich glaube nicht, dass dieses Problem mit git getriggers werden kann, Sie müssen ein pgsql-spezifisches Schema Versionskontrollsystem verwenden. Ich weiß nicht, ob so etwas existiert oder nicht …

Hier ist, was ich in meinen Projekten zu tun versuche:

  • separate Daten und Schema und Standarddaten.

Die databasekonfiguration wird in einer Konfigurationsdatei gespeichert, die nicht der Versionskontrolle unterliegt (.gitignore)

Die databasestandardwerte (zum Einrichten neuer Projekte) ist eine einfache SQL-Datei unter Versionskontrolle.

Erstellen Sie für das databaseschema einen databaseschema-Dump unter der Versionskontrolle.

Die gebräuchlichste Methode besteht darin, Update-Skripts mit SQL-statementen (ALTER Table .. oder UPDATE) zu verwenden. Sie müssen außerdem einen Platz in Ihrer database haben, in dem Sie die aktuelle Version Ihres Schemas speichern.

Werfen Sie einen Blick auf andere große Open-Source-databaseprojekte (Piwik, oder Ihr lieblings CMS-System), sie verwenden alle updatescripts (1.sql, 2.sql, 3.sh, 4.php.5.sql)

Aber dies ist ein sehr zeitintensiver Job, Sie müssen die Updatescripts erstellen und testen, und Sie müssen ein gemeinsames Update-Skript ausführen, das die Version vergleicht und alle erforderlichen Updatescripts ausführt.

Also theoretisch (und das ist was ich suche) konnte man das databaseschema nach jeder Änderung (manuell, conjob, git hooks (vielleicht vor dem commit)) ablegen (und nur in einigen sehr speziellen Fällen update scripts erstellen)

Danach in Ihrem üblichen updatescript (führen Sie die normalen updatescripts für die Sonderfälle aus) und vergleichen Sie dann die Schemas (den Dump und die aktuelle database) und generieren Sie dann automatisch die notwendigen ALTER Statements. Da gibt es einige Tools, die das schon machen können, aber noch keine gute gefunden haben.