Ich muss zugeben, dass ich großer Fan von MySQL bin. Insbesondere der Tool- und Community-Support ist grandios (an dieser Stelle besonders zu empfehlen: das Blog von Percona). Dadurch kann man auch die Datenbank-Queries so optimieren, dass man Geschwindigkeitssteigerungen um Zehnerpotenzen erreichen kann (siehe z.B. bei StackOverflow). Nun kann man zwar einwenden, dass man genau das nicht will – eine Datenbank soll einfach funktionieren und möglichst immer gleich schnell Ergebnisse liefern, egal wie komplex die Anfrage ist. Aber manchmal hat man einfach nicht die Möglichkeit, über Hardware zu skalieren und dann bietet MySQL doch eben sehr, sehr viele Möglichkeiten.

Zurück zum Problem: Beruflich bin ich derzeit mit einer PostgreSQL-Datenbank beschäftigt und muss diese von einem Server auf einen anderen umziehen. Technisch ist das das Gleiche, als ob ich einen komplettes Backup mit anschließendem Restore machen muss. Bei MySQL läuft das relativ trivial ab: Man exportiert zunächst die Datenbank auf dem einen Rechner mittels

mysqldump --all-databases --default-character-set=utf8 --opt --hex-blob -u {ROOT-Username} -p > fullexport.sql

und importiert diese dann auf dem anderen Rechner

mysql -u {ROOT-Username} -p < fullexport.sql

Dabei wird alles mitgenommen, inklusive Benutzer, Rechte, etc. (bei den Rechten muss man später kontrollieren, ob die Zugriffsrechte für die Hosts noch stimmen oder ob sich die auch geändert haben). Zu beachten ist hierbei:

  1. Der Dump blockiert die Datenbank. Daher sollte das idealerweise nicht auf der Produktiv-Datenbank passieren, insbesondere, wenn die groß ist. (Wer das umgehen will, sei auf das Maat-Kit verwiesen und dort auf die Funktion mk-parallel-dump).
  2. Änderungen nach dem Dump werden natürlich nicht übernommen, idealerweise ist das System für die Zeit des Umzugs abgestellt. Aber das gilt ja eh für alle diese Datenbank-Umzüge.

Und bei PostgreSQL?

Es gibt ja viele, die von PostgreSQL wahnsinnig schwärmen und da hatte ich gehofft, dass der Tool-Support gut wäre. Leider ist dem nicht so. Insbesondere unterscheidet sich ein Dump bei PostgreSQL dadurch, dass er entweder nicht alle Informationen mitnimmt (ich habe hier einige Stored Procedures in Verdacht) oder Bibliotheken mit absoluten Pfaden verlinkt (hatte ich als Fehlermeldung beim Wiedereinspielen der Daten gesehen). So oder so heißt das, dass man eben nicht einfach den Dump einspielen kann, sondern man muss vielmehr die Datenbank entsprechend vorbereiten.

Nun, nach vielen, vielen erfolglosen Versuchen und viel, viel Recherche habe ich nun folgende Strategie erarbeitet, die für mich funktioniert:

Export der Daten:

pg_dumpall --globals-only -U postgres -h {Host-alte-Datenbank} -f globals.sql
pg_dump -i -b -Ft -U postgres -h {Host-alte-Datenbank} {Datenbank-Name} > database.tar

Anmerkung am Rande: Die Option -i ist undokumentiert, ich habe sie aus dieser Anleitung übernommen. Auch ein Punkt, der mein Vertrauen in PostgreSQL nicht erhöht.

Import der Daten:

psql -U postgres -f globals.sql postgres
createdb -U postgres {Datenbank-Name}
pg_restore -C -U postgres -d {Datenbank-Name} database.tar >log 2>&1

Enthält die Datenbank Geo-Daten bzw. wird das Modul Postgis mitverwendet, so werden (natürlich) die Funktionen von Postgis nicht mit dem Export mit exportiert, sonder müssen von Hand neu angelegt werden (siehe Postgis-Dokumentation). Dann sind insgesamt die folgenden Schritte durchzuführen:

psql -U postgres -f globals.sql postgres
createdb -U postgres {Datenbank-Name}
createlang plpgsql -U postgres {Datenbank-Name}
psql -d {Datenbank-Name} -U postgres -f /usr/share/postgresql/8.4/contrib/postgis-1.5/postgis.sql
psql -d {Datenbank-Name} -U postgres -f /usr/share/postgresql/8.4/contrib/postgis-1.5/spatial_ref_sys.sql
pg_restore -C -U postgres -d {Datenbank-Name} database.tar >log 2>&1

Wichtig dabei ist folgendes:

  1. Die Version von pgdump und pg_restore dürfen sich nicht unterscheiden. Am besten, man führt beide auf dem gleichen Rechner aus und verbindet pgdump mittels -h mit dem alten Host.
  2. Man muss das für jede Datenbank einzeln machen.

Insgesamt finde ich es schade, dass PostgrSQL es einem so unnötig schwer macht. Das hat sicher gute Gründe und bietet wahrscheinlich an anderer Stelle Vorteile. Aber der große PostgreSQL-Fan bin ich damit nicht geworden.