Sofortige Datenbankklone in PostgreSQL 18
(boringsql.com)- PostgreSQL 18 kann Datenbanken nahezu sofort klonen, indem es die Dateikopierstrategie (FILE_COPY) mit Dateisystem-Klonfunktionen kombiniert
- Mit dem neuen Konfigurationswert
file_copy_method = clonelassen sich Klonfunktionen moderner Dateisysteme (FICLONE) wie XFS, ZFS und APFS nutzen - Benchmark-Ergebnisse zeigen: Beim Klonen einer 6-GB-Datenbank benötigt die bisherige WAL_LOG-Methode etwa 67 Sekunden, die Klonmethode dagegen nur rund 0,2 Sekunden
- Geklonte Datenbanken teilen sich anfangs dieselben physischen Blöcke, werden bei Schreibvorgängen aber per Copy-on-Write getrennt
- Allerdings ist das Klonen nur ohne aktive Verbindungen möglich und funktioniert nur innerhalb eines einzelnen Dateisystems
PostgreSQLs templatebasierte Klonstruktur
- PostgreSQL erstellt bei
CREATE DATABASE dbnameintern eine Kopie der Datenbanktemplate1und erzeugt daraus die neue Datenbank- Das entspricht dem Verhalten von
CREATE DATABASE dbname TEMPLATE template1
- Das entspricht dem Verhalten von
- Statt
template1kann auch eine andere Datenbank angegeben werden, sodass Klonen mit benutzerdefinierten Templates möglich ist - In PostgreSQL 18 wurde dieses Template-System zu einer Struktur für sofortiges Klonen erweitert
CREATE DATABASE ... STRATEGY
- Seit PostgreSQL 15 gibt es den Parameter
CREATE DATABASE ... STRATEGY, mit dem sich die Klonmethode auswählen lässt- Der Standardwert ist
WAL_LOGund führt blockweises Klonen über das Write-Ahead Log aus - Diese Methode reduziert die I/O-Last und verbessert die Unterstützung für Parallelität, ist bei großen Klonvorgängen aber langsam
- Der Standardwert ist
- Mit
STRATEGY=FILE_COPYlässt sich zur klassischen Dateikopiermethode zurückkehren; PostgreSQL 18 ergänzt darauf aufbauend eine neue Klonoption
FILE_COPY und file_copy_method
- Die Einstellung
file_copy_methodin PostgreSQL 18 steuert die Dateikopiermethode auf Betriebssystemebene- Der Standardwert ist
copy; dabei werden alle Bytes gelesen und an einen neuen Ort geschrieben - Bei
clonewird die Klonfunktion des Dateisystems (FICLONE) verwendet, wodurch sofortiges Klonen ohne zusätzlichen Platzverbrauch möglich wird
- Der Standardwert ist
- Unterstützte Dateisysteme: XFS, ZFS, APFS, FreeBSD ZFS
- Einrichtung
- Den PostgreSQL-Cluster auf einem entsprechenden Dateisystem betreiben
file_copy_method = clonesetzen und die Konfiguration neu laden
Benchmark-Ergebnisse
- Nach dem Erstellen einer Testdatenbank (
source_db) mit rund 6 GB wurden zwei Methoden verglichenWAL_LOG: 67.000ms (etwa 67 Sekunden)FILE_COPY+clone: 212ms
- Bei derselben Datenmenge ergibt sich eine mehr als 300-fache Beschleunigung
- Die geklonte Datenbank (
fast_clone) belegt nahezu keinen zusätzlichen Speicherplatz
Funktionsweise der geklonten Daten
- Bei Verwendung von
file_copy_method = clonewerden nur die Dateisystem-Metadaten geklont, sodass beide Datenbanken dieselben physischen Blöcke gemeinsam nutzen - Die von PostgreSQL gemeldete Datenbankgröße bleibt die logische Größe (rund 6 GB)
- Bei Schreibvorgängen greift Copy-on-Write (COW) und trennt die betroffenen Seiten
- Seiten mit geänderten Zeilen
- Seiten, auf die neue Tupel geschrieben werden
- Indexseiten sowie FSM-, Visibility-Map-Seiten usw.
- Auch bei einem
VACUUMwerden zusätzliche Seiten getrennt
Verifikation gemeinsam genutzter Blöcke unter XFS
- Mit dem Befehl
filefrag -vlässt sich prüfen, ob zwei Datenbanken physische Blöcke gemeinsam nutzen- Im Ausgangszustand sind alle Extents als
sharedmarkiert - Werden einige Zeilen aktualisiert, werden die ersten 40 Blöcke (etwa 160 KB) getrennt und auf andere physische Adressen verschoben
- Die übrigen Extents bleiben weiterhin gemeinsam genutzt
- Im Ausgangszustand sind alle Extents als
Hinweise und Einschränkungen
- Beim Klonen darf es keine aktiven Verbindungen zur Quelldatenbank geben
- Das ist eine Einschränkung von PostgreSQL, kein Problem des Dateisystems
- In produktiven Umgebungen ist die Nutzung einer separaten Template-Datenbank üblich
- Klonen ist nur innerhalb eines einzelnen Dateisystems möglich
- Wenn mehrere Tablespaces auf unterschiedlichen Mount-Points liegen, wird auf normales Kopieren zurückgefallen
- In verwalteten Cloud-Diensten (AWS RDS, Google Cloud SQL usw.) ist diese Funktion nicht nutzbar, da kein Zugriff auf das Dateisystem möglich ist
- Auf eigenen VMs oder Bare-Metal-Systemen ist vollständige Kontrolle möglich
Fazit
- Die Funktion
file_copy_method = clonein PostgreSQL 18 nutzt Klonfunktionen auf Betriebssystemebene direkt, um
die Klonzeit großer Datenbanken drastisch zu verkürzen - Damit lassen sich in Test-, Entwicklungs- und Lernumgebungen Datenbank-Workflows mit sofortigem Klonen und schnellem Reset umsetzen
- Dabei müssen jedoch die Einschränkung aktiver Verbindungen und die Bindung an ein einzelnes Dateisystem in der Betriebsarchitektur berücksichtigt werden
1 Kommentare
Hacker-News-Kommentare
Für alle, die nicht warten können oder eine vollständige Instanzisolierung mit PG18 brauchen, habe ich mit ZFS-Snapshots ein Tool namens Velo gebaut, das sofortiges Branching ermöglicht
Es funktioniert mit jeder PostgreSQL-Version, und jeder Branch hat einen eigenen Container und Port
Bei einer 100-GB-DB lässt sich so in etwa 2–5 Sekunden ein Branch erzeugen
Der Unterschied zum Ansatz in PG18 ist, dass kein einzelner Instanz-Stack geteilt wird, sondern eine vollständige Server-Isolierung bereitgestellt wird
GitHub-Link
Als meine Firma früher auf RDS migrierte, haben wir intern ein ähnliches System aufgebaut
Während Produktionsmigrationen traten häufig Probleme auf, also haben wir zur Vermeidung folgende Schritte automatisiert
Durch diesen Ablauf konnten wir viele produktspezifische Bugs finden, die lokal oder in CI nie aufgefallen wären
Danach haben wir das mit einem einfachen Ruby-Skript automatisiert, und soweit ich weiß, wird dieses Skript noch heute verwendet
Dass sich die Strategie des Template-Klonens konfigurieren lässt, habe ich gerade erst gelernt
Ich habe mit Neon Live-Integrationsumgebungen gebaut, und in meinem Golang-Projekt pgtestdb wird für jeden Test eine vollständige Postgres-DB mit allen Schema-Migrationen erzeugt
Ich habe früher in einem Startup gesehen, wie mit btrfs sofortige Staging-DBs erstellt wurden; interessant, wie ähnliche Ideen immer wieder auftauchen
Diese Art von schnellem Klonen und Testen ist ein großer Vorteil von Postgres und Sqlite, und ich wünschte, Clickhouse oder MySQL könnten das ebenfalls
PostgreSQL wirkt inzwischen wie eine Allzweck-DB, die nahezu alle SQL-Anwendungsfälle abdeckt
Und sie ist auch noch kostenlos
Ich frage mich, ob es überhaupt noch einen Grund gibt, andere SQL-DBs zu verwenden
Clickhouse ist für Analytik deutlich schneller, und Datenbanken wie Cassandra sind bei schreibintensiven Workloads im Vorteil
Mit anderen Worten: Jede DB hat weiterhin ihre Stärken
Wenn die Datenmenge steigt, bekommt man Performance-Einbrüche oder Migrationsprobleme
In meinem Fall war die eingebaute Partitionierung zu langsam, sodass ich eigene benutzerdefinierte Partitionen implementieren musste
Diese Entscheidung hat bei steigender Last verschiedene negative Auswirkungen
Das wurde auch im Blogbeitrag von Uber behandelt
Trotzdem vertraue ich in Cloud-Umgebungen Postgres am meisten
Deshalb wird bei großen OLTP-Deployments weiterhin meist MySQL eingesetzt (z. B. YouTube, Uber)
Mit unveränderlichen Datenstrukturen (HAMT) könnte man eine DB bauen, die unabhängig vom Dateisystem sofort klonbar ist
Ich habe es als Theorie bezeichnet, aber tatsächlich auch selbst implementiert
Ich verstehe nicht, warum es nicht mehr HAMT-basierte DBs gibt
Verwandte Dokumentation
Mir war nicht klar, dass in Postgres v15 WAL_LOG zum Standard geworden ist
In parallelen CI-Testumgebungen ist es sinnvoller, wieder zur Strategie FILE_COPY zurückzukehren
Ich hatte dazu schon einmal ein Issue im früheren Projekt integresql erstellt
Ich habe einmal ein einfaches GUI-Tool pgtt gebaut, um Postgres-basierte Apps lokal zu testen
Das vereinfacht die Einrichtung der Entwicklungsumgebung erheblich
Das könnte bei wiederholten SQL-Migrationen hilfreich sein
Ich habe auch andere Blogposts auf der Seite gelesen, und insgesamt sind sie hervorragend
Vor allem habe ich dort zum ersten Mal von den Range-Typen in Postgres erfahren
Ich frage mich, ob es so eine Funktion auch in MariaDB gibt
Ich zerbreche mir den Kopf darüber, weil es so langsam ist, die DB für jeden Test in den Ausgangszustand zurückzusetzen
Da wir in Produktion MariaDB verwenden, ist ein Wechsel der DB schwierig
Postgres wirkt in dieser Hinsicht besser
Das ist ziemlich effizient
AWS unterstützt etwas Ähnliches ebenfalls
Aurora-Klon-Dokumentation
Für Integrationstests ist das unrealistisch