2010-02-01 8 views
12

ich ein PHP-Skript schreibe (was auch Linux-Bash-Befehle verwendet), die indem Sie die folgenden durch Testfälle laufen:Postgres Pg_dump jedes Mal Datenbank in einer anderen Reihenfolge Dumps

Ich verwende eine PostgreSQL-Datenbank (8.4 erstellen 0,2) ...

1.) ein DB 2.) ändern Sie den DB 3.) Speichern Sie eine Datenbanksicherung der DB (pg_dump)

4.) Sie Regressionstests durch Schritte tun 1.) und 2.), und nehmen Sie dann einen anderen Datenbankspeicherauszug und vergleichen Sie ihn (Diff) mit dem ursprünglichen Datenbankspeicherauszug von Schritt Nummer 3.)

Allerdings finde ich, dass pg_dump nicht immer die Datenbank auf die gleiche Weise ausgibt. Es wird die Dinge jedes Mal in einer anderen Reihenfolge ablegen. Wenn ich also die beiden Datenbank-Dumps vergleiche, führt der Vergleich dazu, dass die beiden Dateien unterschiedlich sind, wenn sie tatsächlich gleich sind, nur in einer anderen Reihenfolge.

Gibt es einen anderen Weg, den pg_dump zu machen?

Danke!

Antwort

7

Es ist nicht möglich, pg_dump zum Ausgeben von Daten in einer bestimmten Reihenfolge zu zwingen, da Daten in Festplattenreihenfolge ausgegeben werden - auf diese Weise ist es viel schneller.

Sie können "-a-d" -Optionen für pg_dump verwenden und dann die Ausgabe "sortieren", aber Zeilenumbrüche in Daten machen sortierte Ausgaben nicht importierbar. Aber für einen grundlegenden Vergleich würde es ausreichen, wenn sich etwas änderte.

1

Es ist nicht ungewöhnlich, dass sich PostgreSQL nichtdeterministisch verhält - möglicherweise treten timergesteuerte Reorganisationsprozesse oder etwas Ähnliches im Hintergrund auf. Außerdem ist mir keine Möglichkeit bekannt, pg_dump zu zwingen, bei aufeinanderfolgenden Läufen eine bit-identische Ausgabe zu reproduzieren.

Ich schlage vor, Ihre Vergleichslogik zu ändern, weil es Ihr Vergleich ist, der sich schlecht benimmt - es berichtet Unterschiede, während beide Dumps den gleichen Datenbankstatus darstellen. Dies bedeutet natürlich einige zusätzliche Arbeit, aber meiner Meinung nach ist es der richtige Weg, um das Problem anzugehen.

9

Hier ist es wichtig, Schema und Daten zu unterscheiden. Das Schema wird in einer ziemlich deterministischen Reihenfolge ausgegeben, wobei die meisten Objekte alphabetisch durch Abhängigkeiten zwischen Objekten eingeschränkt sind. Es gibt einige begrenzte Fälle, in denen die Reihenfolge nicht vollständig eingeschränkt ist und für einen externen Beobachter zufällig erscheinen mag, die jedoch in der nächsten Version behoben werden kann.

Die Daten auf der anderen Seite werden in der Datenträgerreihenfolge ausgegeben. Dies ist normalerweise das, was Sie wollen, weil Sie möchten, dass die Speicherauszüge schnell sind und keine wahnsinnigen Ressourcenmengen zum Sortieren verwenden. Was Sie beobachten könnten, ist, dass Sie beim Ändern der Datenbank ein UPDATE durchführen, das den alten Wert löscht und den neuen Wert am Ende anfügt. Und das wird natürlich deine Diff-Strategie stören.

Ein Werkzeug, das für Ihren Zweck besser geeignet sein könnte, ist pg_comparator.

+0

+1 Für pg_comparator ich vorher nicht kannte. –

+1

Ein aktualisierterer Link ist http://www.coelho.net/pg_comparator/ –

1

Wenn Sie nur Interesse an dem Schema:

Sie Ihren diff Tisch Tisch-by-Verwendung eine Kombination dieser Optionen tun könnten das Schema für nur eine Tabelle zu einem Zeitpunkt, zu entleeren. Sie können sie dann einzeln vergleichen oder sie alle in einer bekannten Reihenfolge zu einer Datei katalysieren.

-s, --schema-only   dump only the schema, no data 
-t, --table=TABLE   dump the named table(s) only 

Um die Liste der Tabellen zu erzeugen information_schema.tables zu der oben genannten Abfrage zu füttern.

11

Hier ist ein handliches Skript für die Vorverarbeitung pg_dump Ausgang für diffing und Speicherung in der Versionskontrolle ist es besser geeignet zu machen:

https://github.com/akaihola/pgtricks

pg_dump_splitsort.py teilt die Sicherung in den folgenden Dateien:

  • 0000_prologue.sql: alles bis zum ersten COPY
  • 0001_<schema>.<table>.sql
    .
    .
    NNNN_<schema>.<table>.sql: Daten für jede Tabelle durch das erste Feld sortiert
  • 9999_epilogue.sql: alles nach dem letzten COPY

Die Dateien für Tabellendaten sind so eine einfache sortierte Verkettung aller Dateien nummeriert kann verwendet werden, neu zu erstellen, die Datenbank:

$ cat *.sql | psql <database> 

ich gefunden habe, dass ein guter Weg, um einen kurzen Blick auf Unterschiede zwischen den Deponien nehmen Sie die meld Werkzeug auf das gesamte Verzeichnis zu verwenden ist:

Speichern der Dump in Versionskontrolle gibt auch eine anständige Sicht auf die Unterschiede. Hier ist, wie git konfigurieren Farbe zu verwenden, in diffs:

# ~/.gitconfig 
[color] 
     diff = true 
[color "diff"] 
     frag = white blue bold 
     meta = white green bold 
     commit = white red bold 

Hinweis: Wenn Sie erstellt haben/gelöscht/umbenannt Tabellen, erinnern alle .sql Dateien vor der Nachbearbeitung des neuen Dump zu löschen.

+0

Sie haben meinen Tag gerettet! :) – giaffa86

2

Ab Mai 2010 ein patch to pg_dump besteht, dass in dieser Angelegenheit für alle Interessierten nützlich sein kann - es fügt hinzu: „--ordered“ Option zu diesem Programm:

--ordered Verwendung werden die Daten von bestellen Primärschlüssel oder eindeutiger Index, wenn eine vorhanden ist, und verwenden Sie die "kleinste" Bestellung (dh die kleinste Anzahl von Spalten für eine eindeutige Reihenfolge erforderlich).

Beachten Sie, dass - ordered Ihren Datenbankserver zerquetschen kann, wenn Sie versuchen, sehr große Tabellen zu bestellen, also vernünftig verwenden.

Ich habe es nicht getestet, aber ich denke, es ist einen Versuch wert.

+0

Hallo Zifot, der Link ist kaputt, noch 2 Jahre bestanden, möchte es versuchen, aber andere Referenzen nicht finden. Können Sie den Arbeitslink bereitstellen? Vielen Dank. – Igor

+0

@Igor, ich habe gerade den Link aktualisiert. – zifot

+0

Ein sehr interessanter Patch/Zusatz, der es leider nicht zum Release geschafft hat. –

0

Wenn die Leistung ist weniger wichtig als um Sie nutzen könnten:

COPY (select * from your_table order by some_col) to stdout 
     with csv header delimiter ','; 

Siehe COPY (9.5)

Verwandte Themen