1 Punkte von GN⁺ 2025-12-24 | 1 Kommentare | Auf WhatsApp teilen
  • PostgreSQL 18 kann Datenbanken nahezu sofort klonen, indem es die Dateikopierstrategie (FILE_COPY) mit Dateisystem-Klonfunktionen kombiniert
  • Mit dem neuen Konfigurationswert file_copy_method = clone lassen 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 dbname intern eine Kopie der Datenbank template1 und erzeugt daraus die neue Datenbank
    • Das entspricht dem Verhalten von CREATE DATABASE dbname TEMPLATE template1
  • Statt template1 kann 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_LOG und 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
  • Mit STRATEGY=FILE_COPY lässt sich zur klassischen Dateikopiermethode zurückkehren; PostgreSQL 18 ergänzt darauf aufbauend eine neue Klonoption
Anzeige

FILE_COPY und file_copy_method

  • Die Einstellung file_copy_method in PostgreSQL 18 steuert die Dateikopiermethode auf Betriebssystemebene
    • Der Standardwert ist copy; dabei werden alle Bytes gelesen und an einen neuen Ort geschrieben
    • Bei clone wird die Klonfunktion des Dateisystems (FICLONE) verwendet, wodurch sofortiges Klonen ohne zusätzlichen Platzverbrauch möglich wird
  • Unterstützte Dateisysteme: XFS, ZFS, APFS, FreeBSD ZFS
  • Einrichtung
    • Den PostgreSQL-Cluster auf einem entsprechenden Dateisystem betreiben
    • file_copy_method = clone setzen und die Konfiguration neu laden

Benchmark-Ergebnisse

  • Nach dem Erstellen einer Testdatenbank (source_db) mit rund 6 GB wurden zwei Methoden verglichen
    • WAL_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
Anzeige

Funktionsweise der geklonten Daten

  • Bei Verwendung von file_copy_method = clone werden 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 VACUUM werden zusätzliche Seiten getrennt

Verifikation gemeinsam genutzter Blöcke unter XFS

  • Mit dem Befehl filefrag -v lässt sich prüfen, ob zwei Datenbanken physische Blöcke gemeinsam nutzen
    • Im Ausgangszustand sind alle Extents als shared markiert
    • 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
Anzeige

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 = clone in 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

 
GN⁺ 2025-12-24
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

    • In einem anderen Kommentar wurde die Nutzung von Claude Code kritisiert, aber nachdem ich das Demo-Video auf der GitHub-Seite gesehen habe, fand ich es interessant
    • Heutzutage wird die meiste Software mit Hilfe von AI-Agenten geschrieben, daher verstehe ich nicht, warum sich darüber beschwert wird. Der Ansatz ist interessant
    • Ich war gerade dabei, etwas Ähnliches mit btrfs zu prototypen
    • Ich fand die Formulierung mit „du“ interessant, war dann aber etwas überrascht, als von Plagiat die Rede war
  • 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

    1. Die RDS-DB klonen oder aus einem Backup eine neue Instanz erzeugen
    2. CNAME oder öffentliche IP aus der ARN extrahieren
    3. In die DB-Verbindungskonfiguration der App übernehmen
    4. Die Migration in einer gefälschten Produktionsumgebung ausführen
      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
    • Ich hasse solche Bugs auch, bei denen Migrationen wegen „Dateneigenheiten nur in Produktion fehlschlagen“. Mehr als einmal musste ich deshalb schon ein Release absagen
  • 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

    • Postgres ist großartig, aber bei MySQL ist Master-Master-Replikation einfacher, und MongoDB macht geografische Verteilung und Sharding unkompliziert
      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
    • Die Aussage „kann alles gut“ ist übertrieben
      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
    • Bei Postgres ist die MVCC-Implementierung (copy-on-write) immer noch ineffizient
      Diese Entscheidung hat bei steigender Last verschiedene negative Auswirkungen
    • Früher war MySQL/InnoDB bei update-lastigen Workloads besser
      Das wurde auch im Blogbeitrag von Uber behandelt
      Trotzdem vertraue ich in Cloud-Umgebungen Postgres am meisten
    • Für Postgres gibt es noch keinen ausgereiften Ersatz auf dem Niveau von Vitess
      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

    • Ich bin der Autor von ClickHouse, und ClickHouse unterstützt Tabellenklonen ebenfalls mit unveränderlichen Datenteilen
      Verwandte Dokumentation
    • Ich frage mich, ob Datomic diese Klonfunktion ebenfalls eingebaut hat. Ich wollte es schon lange ausprobieren, war aber mental noch nie bereit, damit tatsächlich eine App zu bauen
  • 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

    • Allein aus dem README werde ich nicht ganz schlau; ich frage mich, ob Templates dort wie Snapshots behandelt werden
      Das könnte bei wiederholten SQL-Migrationen hilfreich sein
    • Ein GUI-Screenshot im README wäre hilfreich, und der Docker-Link ist kaputt
  • 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

    • Range-Typen sind wirklich nützlich für Dinge wie die Berechnung von Überschneidungen bei Zeit-/Datumsintervallen
  • 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

    • Wenn man jeden Test in einer Transaktionssitzung ausführt und am Ende ein Rollback macht, lässt sich der Ursprungszustand schnell wiederherstellen
      Das ist ziemlich effizient
    • Wenn ein DB-Neustart akzeptabel ist, kann man auch LVM oder btrfs-Snapshots auf Dateisystemebene verwenden
  • AWS unterstützt etwas Ähnliches ebenfalls
    Aurora-Klon-Dokumentation

    • Aurora-Klone arbeiten auf Storage-Ebene mit copy-on-write, aber man muss trotzdem noch einen neuen Cluster bereitstellen, was etwa 10 Minuten dauert
      Für Integrationstests ist das unrealistisch
    • Aurora klont auf Cluster-Ebene, während es hier um Klonen auf Datenbank-Ebene geht