In der heutigen datengetriebenen Welt stehen Unternehmen vor der Herausforderung, immer größere Mengen an Daten performant, sicher und konsistent zu verwalten. PostgreSQL hat sich als eine der leistungsfähigsten und zuverlässigsten relationalen Datenbanken etabliert und wird in zahlreichen Anwendungen eingesetzt. Doch mit wachsenden Anforderungen an Skalierbarkeit und Verfügbarkeit stößt dieses bewährte System insbesondere bei sehr hohen Lasten häufig an seine Grenzen. Ein oft diskutiertes Mittel, um diese Grenzen zu überwinden, ist das sogenannte Sharding. Dabei handelt es sich um die horizontale Aufteilung der Datenbank in mehrere kleinere Einheiten.
Allerdings wird häufig fälschlicherweise angenommen, dass Sharding automatisch eine verteilte Datenbanklösung darstellt. Dieser Irrtum hat weitreichende Konsequenzen, denn Sharding bietet nicht zwangsläufig die Konsistenz-, Verfügbarkeits- und Transaktionsgarantien, die von echten verteilten Systemen erwartet werden können. PostgreSQL selbst ist ursprünglich als monolithisches System konzipiert. Das bedeutet, dass alle Daten und Transaktionen in einem einzigen Server verwaltet und bearbeitet werden, was eine starke Konsistenz und vollständige ACID-Eigenschaften garantiert. Diese ACID-Eigenschaften umfassen Atomicity (atomare Durchführung von Transaktionen), Consistency (Erhaltung der Datenintegrität), Isolation (Unabhängigkeit gleichzeitiger Transaktionen) und Durability (dauerhafte Speicherung von Daten).
Gerade bei Anwendungen, die auf finanzielle Transaktionen, kritische Geschäftsvorgänge oder sensible Daten angewiesen sind, sind diese Garantien unerlässlich. Mit dem Ziel, die Skalierbarkeit zu erhöhen, greifen viele Entwickler zu Sharding-Lösungen, bei denen die Daten horizontal auf mehrere PostgreSQL-Instanzen verteilt werden. Ein bekanntes Beispiel ist die Erweiterung Citus, die mehrere PostgreSQL-Server koordiniert und so scheinbar eine verteilte Umgebung schafft. Dabei wird jedoch übersehen, dass die einzelnen PostgreSQL-Instanzen keine Kenntnis voneinander besitzen und miteinander nicht direkt kommunizieren. Diese Koordination erfolgt meist durch eine zusätzliche Schicht, die Anfragen an den richtigen Datenbank-Server weiterleitet.
Solange eine Transaktion nur eine einzelne Datenpartition betrifft, verhalten sich diese Systeme ähnlich wie ein herkömmliches PostgreSQL. Sobald jedoch Transaktionen mehrere Partitionsserver einbeziehen, treten jedoch fundamentale Einschränkungen auf. Ein entscheidender Punkt ist die Gewährleistung von vollständigen ACID-Eigenschaften bei Multi-Shard-Transaktionen. Während die atomare Durchführung von Transaktionen dank des Zwei-Phasen-Commit-Protokolls (2PC) technisch erreicht werden kann, bietet 2PC keine Isolation der Transaktionen über mehrere Knoten hinweg. Das bedeutet, dass Änderungen auf verschiedenen Shards nicht immer gleichzeitig sichtbar werden, was zu Inkonsistenzen führt, die in monolithischen Datenbanksystemen ausgeschlossen wären.
Ein anschauliches Beispiel hierfür ist ein Kontoübertrag zwischen zwei Konten, die jeweils auf unterschiedlichen Shards liegen. Die atomare Verpflichtung wird zwar sichergestellt, aber die Sichtbarkeit der Aktualisierungen erfolgt asynchron. Während ein Leser bereits die Belastung auf dem ersten Konto erkennt, kann die Gutschrift auf dem zweiten Konto noch nicht sichtbar sein, was zwischendurch falsche oder unvollständige Daten liefert. Dieses Phänomen wird als eventual consistency bezeichnet und steht im Widerspruch zur idealen Isolation eines Transaktionssystems. Die fehlende verteilte Snapshoterstellung ist eine wesentliche Ursache dieses Problems.
Da die einzelnen PostgreSQL-Instanzen unabhängig agieren und keine gemeinsame Sicht auf den Transaktionszustand herstellen, besteht kein globaler Konsens über den aktuellen Zustand der Datenbank. Als Folge kann lediglich das Niveau der „Read Committed“-Isolation erreicht werden, wohingegen komplexere und strengere Isolationsebenen wie „Serializable“ nicht unterstützt werden. Dies ist insbesondere für Anwendungen kritisch, die auf strikte Konsistenz angewiesen sind. Es gilt anzumerken, dass die Begrenzungen von Lösungen wie Citus im Bereich der Dokumentation und Kommunikation häufig nur unzureichend und versteckt erwähnt werden. Die Standardisierungen und technischen Aufbauten solcher Systeme sind meist auf Performance unter moderaten Konsistenzanforderungen optimiert, wobei Verfügbarkeit und Skalierbarkeit im Vordergrund stehen.
Die Entwicklercommunity findet sich hier mit einem Kompromiss ab, der zwar eine horizontale Skalierung ermöglicht, jedoch mit einem Verzicht auf umfassende ACID-Garantie bei verteilten Transaktionen einhergeht. Der Einsatz eines verteilten Datenbanksystems bietet hingegen eine komplett andere Architektur. Solche Systeme, zu denen beispielsweise YDB gehört, sind von Grund auf für verteilte Datenhaltung und Verarbeitung konzipiert. Sie verwalten Transaktionen über Knoten hinweg mit einem verteilten Konsensmechanismus und bieten striktere Isolationsebenen durch verteilte Snapshots. Dies stellt sicher, dass alle Teilnehmer einer Transaktion zur selben Zeit einen konsistenten und einheitlichen Blick auf die Daten haben, ohne Inkonsistenzen durch verzögerte Sichtbarkeiten.
Der Nachteil von vollständig verteilten Transaktionen liegt in den höheren Kommunikationskosten und der Komplexität des Protokolls. Das Zwei-Phasen-Commit-Protokoll, kombiniert mit verteilten Snapshots, erfordert mehrere Netzwerk-Roundtrips pro Transaktion, was sich auf die Latenz auswirkt. Allerdings sind moderne Rechenzentren und ausgeklügelte Systemarchitekturen in der Lage, diese Latenzen so gering zu halten, dass der Vorteil der korrekten Konsistenz oft den Leistungsverlust überwiegt. Die Differenz zu schlichteren Sharding-Lösungen ist unter realistischen Nutzungsbedingungen häufig marginal. Die Herausforderung besteht also darin, abzuwägen, welche Anforderungen die jeweilige Anwendung stellt.
Für einfache Webanwendungen oder Szenarien, bei denen eventual consistency akzeptabel ist, können Sharding-Ansätze wie Citus eine kostengünstige und praktikable Lösung darstellen. Sobald jedoch kritische Datenverarbeitung, finanzielle Operationen oder andere stark konsistenzabhängige Prozesse im Spiel sind, erweisen sich verteilte Systeme mit echten ACID-Eigenschaften als unverzichtbar. Zusammenfassend lässt sich sagen, dass Sharding und verteilte Datenbanksysteme zwar Gemeinsamkeiten bei der Verteilung von Daten aufweisen, jedoch grundlegend unterschiedliche Konzepte und Garantien umfassen. Sharding alleine ist kein Ersatz für die komplexe Infrastruktur, die notwendig ist, um echte verteilte Transaktionen mit vollständiger Konsistenz und Isolation zu gewährleisten. PostgreSQL ist in seinem Standard-Setup hervorragend geeignet für viele Anwendungsfälle, stößt aber bei extremen Skalierungsanforderungen und strikten ACID-Ansprüchen an seine Grenzen.