Powrót do strony głównej

OLTP-rdzeń: API i adaptive tuning w systemie bazodanowym

Nowy system OLTP wykorzystuje per-tablespace page size, ścisłe kontrakty API między warstwami i Resource Broker dla adaptive tuning. Diagnostyka przez eBPF/USDT. Architektura eliminuje ręczny tuning i degradację.

Budujemy OLTP-rdzeń: od page size do eBPF
Advertisement 728x90

Implementacja jądra OLTP: kontrakty API, rozmiar strony i adaptacyjne strojenie

Specjaliści tworzący nową bazę danych OLTP zaimplementowali ścisłą architekturę z izolowanymi warstwami za pomocą interfejsów trait w Rust. Każda warstwa ma precyzyjne kontrakty API, rozmiar strony jest konfigurowalny dla każdego tablespace, a konfiguracja jest zarządzana przez Resource Broker bez ręcznego tuningu. Diagnostyka jest zintegrowana poprzez USDT i eBPF.

Ustawienia rozmiaru strony i tablespace

Rozmiar strony danych waha się od 4-8 KB dla czystego OLTP do 16-32 KB dla HTAP na NVMe. Każdy tablespace to oddzielny plik z niezmiennym rozmiarem strony po utworzeniu. Domyślnie 16 KB. PageId jest złożony: [tablespace_id:16][page_index:48]. BufferPool kieruje zapytania do podbuforów według rozmiaru.

Superblok na początku pliku przechowuje metadane tablespace niezależnie od rozmiaru strony. Podczas montowania sprawdzana jest konfiguracja; niezgodność powoduje odmowę uruchomienia bez degradacji.

Google AdInline article slot

Architekturalne warstwy i kontrakty API

Jądro jest podzielone na cztery warstwy:

  • Warstwa Adaptera (async tokio): kończy TLS, parsuje protokół sieciowy.
#[async_trait]
pub trait NetworkAdapter {
    async fn handle_connection(&self, stream: Box<dyn ConnectionStream>) -> Result<(), NetworkError>;
}
  • Warstwa Kompatybilności: parsuje SQL do AST, emuluje pg_catalog, tłumaczy na LogicalPlan, odrzuca nieobsługiwane funkcje (błąd 0A000).
pub trait CompatLayer {
    fn translate_query(&self, ast: SqlAst) -> Result<LogicalPlan, CompatError>;
}
  • Silnik Rdzenia (sync): optymalizator, executor, menedżer transakcji. Wykonywany w puli spawn_blocking.
pub trait ExecutionEngine {
    fn execute_plan(&self, plan: LogicalPlan, session: &Session) -> Result<ResultSet, ExecutionError>;
}
  • Menedżer Magazynu: fasada nad PageProvider i TransactionLogSink. Jądro żąda stron i rekordów UNDO.
pub trait StorageManager {
    fn pin_page(&self, page_id: PageId, mode: LockMode) -> Result<PageGuard, StorageError>;
    fn append_undo(&self, txn_id: TxnId, record: UndoRecord) -> Result<UndoPtr, StorageError>;
}

Granice warstw zapobiegają wyciekom szczegółów: metryki blokad nie uwzględniają asynchronicznego oczekiwania.

Adaptacyjne strojenie i Resource Broker

Około 60 parametrów jest podzielonych na budżety, bariery ochronne i nadpisy. Operator ustawia limity na wysokim poziomie:

Google AdInline article slot
[resources]
memory_budget = "16GB"
cpu_budget    = "auto"
io_iops       = 5000

Doradcy (MemoryAdvisor, IoAdvisor, CpuAdvisor) redistribuują zasoby co sekundę:

  • CpuAdvisor: DOP i pula wątków przeciwko throttlingowi.
  • MemoryAdvisor: BufferPool vs work_mem pod obciążeniem.
  • IoAdvisor: priorytet transakcjom, świadomość burstów w chmurze.

Mechanizmy ochronne

  • Hystereza: okno 5 s, kroki 5% przeciwko oscylacjom.
  • Twarde minima: min. 128 MB dla BufferPool/UNDO.
  • Płynne przejście: nowe limity dla nowych alokacji.
  • Eksperckie nadpisy blokują autotuning.

Tło czyszczenia logu UNDO zamiast VACUUM. Zmiany w runtime bez restartu.

Diagnostyka: sondy USDT i eBPF

Mechanizmy diagnostyczne są wbudowane w binarny plik. Sondy USDT do analizy runtime, eBPF do śledzenia bez narzutu.

Google AdInline article slot

Co ważne:

  • Rozmiar strony per-tablespace z ochroną przy starcie.
  • Ścisłe kontrakty trait między warstwami zapobiegają wyciekom.
  • Resource Broker: budżety → autotuning z barierami.
  • Diagnostyka przez eBPF/USDT w jądrze.
  • Rezygnacja z ręcznego tuningu na rzecz mechanizmów adaptacyjnych.

— Editorial Team

Advertisement 728x90

Czytaj dalej