Powrót do strony głównej

Projektowanie OLTP BD w Rust: zasady

Artykuł opisuje zasady projektowania OLTP-bazy danych od zera w Rust: restrictive by default, contract-first poprzez traits, hybrydowa asynchroniczność. Zaimplementowano unified storage, MVCC, WAL. Nacisk na przewidywalność i niezawodność dla production.

OLTP BD od zera: architektura i realizacja w Rust
Advertisement 728x90

Architektura bazy danych OLTP: od zasad do implementacji w Rust

Zaimplementowano kluczowe podsystemy silnika OLTP: unified storage w jednym pliku na bazę, disk-backed storage z UNDO-log MVCC, WAL i recovery według ARIES, wspólny BufferPool, silnik in-memory oraz protokół pgwire zgodny z PostgreSQL. Kod działa, ale wymaga testów obciążeniowych i stabilizacji przypadków brzegowych. To nie produkt finalny, lecz wczesny etap z ustalonymi kontraktami.

Główne zasady projektowania

Projekt opiera się na ścisłych regułach podejmowania decyzji. Każda nowa decyzja musi ich przestrzegać lub uzasadniać odstępstwo.

Restrictive by Default

Komponenty mają wyraźne limity z zachowaniem fail-closed zamiast throttlingu. Zapewnia to przewidywalność pod obciążeniem.

Google AdInline article slot

| Komponent | Granica | Działanie przy naruszeniu | SQLSTATE |

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

| BufferPool | buffer_pool_size_mb | Eviction (CLOCK), flush z priorytetem WAL | — |

Google AdInline article slot

| TxnWriteSet | txn_max_write_set_mb | Odrzucenie DML | 54023 |

| UndoStore | undo_max_size_mb | Odrzucenie zapisów | 53100 |

| Connection pool | max_connections | Odrzucenie nowych połączeń | 53300 |

Google AdInline article slot

| Statement timeout | statement_timeout_ms | Anulowanie zapytania | 57014 |

| Snapshot age | max_snapshot_age | Wymuszenie zamknięcia przestarzałych snapshotów | 40001 |

Fail-closed zapewnia jasne SQLSTATE dla retry lub circuit breaker w aplikacji.

Podejście Contract-First

Kontrakty architektoniczne są ustalane w traitach Rust: TableEngine, PageProvider, TransactionLogSink, StorageIo. Zapobiega to dryfowi implementacji, sprawdzając niezmienniki na etapie kompilacji.

Wybór Rust

Rust wybrano ze względu na przewidywalne opóźnienia, kontrolę alokacji i bezpieczeństwo typów. Send/Sync na granicach async/sync, jawne błędy zamiast problemów runtime. C++ wymaga dodatkowej dyscypliny, Go nie nadaje się z powodu GC dla opóźnień ogonowych OLTP.

Podział odpowiedzialności

Baza danych działa jako data engine bez logiki biznesowej: brak triggerów, PL/pgSQL, procedur składowanych na starcie. User-defined functions możliwe później z sandboxingiem i bez efektów ubocznych.

Hybrydowa asynchroniczność

  • Warstwa sieciowa/pgwire: async (accept, TLS, send).
  • Jądro (query execution, storage, WAL, MVCC): sync dla poprawności i debugowania.
  • Granica jednokierunkowa przez bridge.

StorageIo jest abstrahowany dla przyszłego async I/O bez przepisywania transakcji.

| Warstwa | Runtime | Przykłady |

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

| Network/Protocol | async | pgwire, TLS |

| Query Execution | sync | plan, execute |

| Storage/WAL | sync (async I/O później) | HeapStore, BufferPool |

| MVCC/Transactions | sync | snapshot, locks |

Zgodność z PostgreSQL

Pgwire zapewnia integrację z driverami i ORM bez migracji klienta. Zgodność na poziomie wire przez warstwę boundary, bez kopiowania wewnętrznych struktur PostgreSQL (MVCC heap, VACUUM). Jądro zachowuje swobodę architektoniczną.

Ograniczenia platformowe i niezawodność

Linux-only dla skupienia na io_uring, eBPF bez kompromisów wieloplatformowych. Priorytety: brak uszkodzenia danych, bezpieczny rollback optymalizacji, odporność na user input, wbudowane bezpieczeństwo.

Co jest ważne

  • Restrictive by Default z fail-closed dla przewidywalności pod obciążeniem.
  • Contract-First przez Rust traits dla kontroli niezmienników.
  • Hybryda async/sync: stabilność jądra przed przyspieszeniem I/O.
  • Zgodność pgwire bez kopiowania internals PostgreSQL.
  • Data engine bez logiki biznesowej dla czystości i testowalności.

— Editorial Team

Advertisement 728x90

Czytaj dalej