Zurück zur Startseite

OLTP DB in Rust entwerfen: Prinzipien

Der Artikel beschreibt die Prinzipien des Entwurfs einer OLTP-Datenbank von Grund auf in Rust: standardmäßig restriktiv, contract-first via traits, hybride Asynchronität. Implementiert einheitlichen Speicher, MVCC, WAL. Fokus auf Vorhersagbarkeit und Zuverlässigkeit für die Produktion.

OLTP DB von Grund auf: Architektur und Rust-Implementierung
Advertisement 728x90

OLTP-Datenbankarchitektur: Von Prinzipien zur Implementierung in Rust

Wichtige OLTP-Engine-Subsysteme wurden implementiert: einheitlicher Speicher in einer einzelnen Datei pro Datenbank, speicherbasierte Speicherung mit UNDO-Log-MVCC, WAL- und ARIES-basierte Wiederherstellung, ein gemeinsamer BufferPool, eine In-Memory-Engine und ein mit PostgreSQL kompatibles pgwire-Protokoll. Der Code ist funktionsfähig, erfordert jedoch Lasttests und Stabilisierung von Randfällen. Es handelt sich nicht um ein Endprodukt, sondern um eine frühe Phase mit etablierten Verträgen.

Kernentwurfsprinzipien

Das Projekt stützt sich auf strenge Regeln für Entscheidungsfindung. Jede neue Entscheidung muss sich daran halten oder Abweichungen begründen.

Restriktiv als Standard

Komponenten haben explizite Grenzen mit Fail-Closed-Verhalten anstelle von Drosselung. Dies gewährleistet Vorhersagbarkeit unter Last.

Google AdInline article slot

| Komponente | Grenze | Aktion bei Verletzung | SQLSTATE |

|-----------|---------|------------------------|----------|

| BufferPool | buffer_pool_size_mb | Auslagerung (CLOCK), WAL-first Flush | — |

Google AdInline article slot

| TxnWriteSet | txn_max_write_set_mb | DML ablehnen | 54023 |

| UndoStore | undo_max_size_mb | Schreibvorgänge ablehnen | 53100 |

| Verbindungspool | max_connections | Neue Verbindungen ablehnen | 53300 |

Google AdInline article slot

| Statement-Timeout | statement_timeout_ms | Abfrage abbrechen | 57014 |

| Snapshot-Alter | max_snapshot_age | Veraltete Snapshots zwangsweise schließen | 40001 |

Fail-Closed bietet klare SQLSTATE-Codes für Anwendungs-Wiederholungs- oder Circuit-Breaker-Logik.

Vertragsorientierter Ansatz

Architektonische Verträge sind in Rust-Traits definiert: TableEngine, PageProvider, TransactionLogSink, StorageIo. Dies verhindert Implementierungsabweichungen durch Durchsetzung von Invarianten zur Kompilierzeit.

Warum Rust?

Rust wurde für seine vorhersagbare Latenz, Speicherzuweisungskontrolle und Typsicherheit gewählt. Send/Sync an Async/Sync-Grenzen, explizite Fehler statt Laufzeitprobleme. C++ erfordert zusätzliche Disziplin, während Go aufgrund von GC für OLTP-Tail-Latenz ungeeignet ist.

Trennung der Verantwortlichkeiten

Die Datenbank fungiert als Daten-Engine ohne Geschäftslogik: zunächst keine Trigger, PL/pgSQL oder gespeicherte Prozeduren. Benutzerdefinierte Funktionen können später mit Sandboxing und ohne Nebeneffekte hinzugefügt werden.

Hybride Asynchronität

  • Netzwerk-/pgwire-Schicht: asynchron (Annahme, TLS, Senden).
  • Kern (Abfrageausführung, Speicher, WAL, MVCC): synchron für Korrektheit und Debugging.
  • Grenze ist unidirektional über eine Brücke.

StorageIo ist abstrahiert, um zukünftige asynchrone I/O ohne Neuschreiben der Transaktionslogik zu ermöglichen.

| Schicht | Laufzeit | Beispiele |

|------|---------|---------|

| Netzwerk/Protokoll | asynchron | pgwire, TLS |

| Abfrageausführung | synchron | Plan, Ausführung |

| Speicher/WAL | synchron (asynchrone I/O später) | HeapStore, BufferPool |

| MVCC/Transaktionen | synchron | Snapshot, Sperren |

PostgreSQL-Kompatibilität

Pgwire ermöglicht Integration mit Treibern und ORMs ohne Client-Migrationen. Kompatibilität erfolgt auf Protokollebene über eine Grenzschicht, ohne PostgreSQL-Interna (MVCC-Heap, VACUUM) zu kopieren. Der Kern behält architektonische Freiheit.

Plattformbeschränkungen und Zuverlässigkeit

Nur Linux, um sich auf io_uring und eBPF ohne plattformübergreifende Kompromisse zu konzentrieren. Prioritäten: keine Datenkorruption, sichere Rücknahme von Optimierungen, Resilienz gegenüber Benutzereingaben, integrierte Sicherheit.

Wichtige Erkenntnisse

  • Restriktiv als Standard mit Fail-Closed für Vorhersagbarkeit unter Last.
  • Vertragsorientiert über Rust-Traits für Invariantenkontrolle.
  • Hybride Async/Sync: Kernstabilität vor I/O-Beschleunigung.
  • Pgwire-Kompatibilität ohne Kopieren von PostgreSQL-Interna.
  • Daten-Engine ohne Geschäftslogik für Reinheit und Testbarkeit.

— Editorial Team

Advertisement 728x90

Weiterlesen