返回首页

使用 Rust 设计 OLTP DB:原则

本文描述了使用 Rust 从零设计 OLTP 数据库的原则:默认限制、通过 traits 实现契约优先、混合异步。实现了统一存储、MVCC、WAL。专注于生产环境的 predictability 和可靠性。

从零构建 OLTP DB:架构和 Rust 实现
Advertisement 728x90

OLTP数据库架构:从设计原则到Rust实现

关键OLTP引擎子系统已实现:每个数据库采用单一文件的统一存储、基于磁盘存储与UNDO日志的MVCC、WAL和ARIES恢复机制、共享缓冲池、内存引擎,以及兼容PostgreSQL的pgwire协议。代码功能完整,但需进行负载测试和边缘情况稳定性验证。这并非最终产品,而是处于早期阶段,已建立明确契约。

核心设计原则

项目依赖严格的决策规则。每个新决策必须遵守这些规则,或对任何偏差提供合理解释。

默认限制性

组件具有明确的限制,采用故障关闭行为而非节流机制。这确保了负载下的可预测性。

Google AdInline article slot

| 组件 | 限制 | 违规操作 | SQLSTATE |

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

| 缓冲池 | buffer_pool_size_mb | 淘汰(CLOCK算法),优先WAL刷新 | — |

Google AdInline article slot

| 事务写集 | txn_max_write_set_mb | 拒绝DML操作 | 54023 |

| Undo存储 | undo_max_size_mb | 拒绝写入 | 53100 |

| 连接池 | max_connections | 拒绝新连接 | 53300 |

Google AdInline article slot

| 语句超时 | statement_timeout_ms | 取消查询 | 57014 |

| 快照年龄 | max_snapshot_age | 强制关闭陈旧快照 | 40001 |

故障关闭机制为应用程序重试或断路器逻辑提供清晰的SQLSTATE代码。

契约优先方法

架构契约在Rust特征中定义:TableEngine、PageProvider、TransactionLogSink、StorageIo。这通过编译时强制不变量防止实现漂移。

为何选择Rust?

选择Rust因其可预测的延迟、内存分配控制和类型安全性。在异步/同步边界使用Send/Sync,采用显式错误而非运行时问题。C++需要额外纪律,而Go因垃圾回收不适合OLTP尾部延迟场景。

职责分离

数据库作为数据引擎运行,不包含业务逻辑:初始阶段无触发器、PL/pgSQL或存储过程。用户定义函数可能后续添加,需沙箱化且无副作用。

混合异步性

  • 网络/pgwire层:异步(接受、TLS、发送)。
  • 核心(查询执行、存储、WAL、MVCC):同步以确保正确性和调试。
  • 边界通过桥接单向连接。

StorageIo被抽象化,允许未来异步I/O而无需重写事务逻辑。

| 层 | 运行时 | 示例 |

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

| 网络/协议 | 异步 | pgwire、TLS |

| 查询执行 | 同步 | 计划、执行 |

| 存储/WAL | 同步(未来异步I/O) | HeapStore、BufferPool |

| MVCC/事务 | 同步 | 快照、锁 |

PostgreSQL兼容性

Pgwire支持与驱动程序和ORM集成,无需客户端迁移。兼容性通过边界层在协议级别实现,不复制PostgreSQL内部机制(MVCC堆、VACUUM)。核心保持架构自由。

平台约束与可靠性

仅限Linux以专注于io_uring和eBPF,无需跨平台妥协。优先事项:无数据损坏、安全回滚优化、对用户输入的弹性、内置安全性。

关键要点

  • 默认限制性,采用故障关闭确保负载下的可预测性。
  • 契约优先,通过Rust特征控制不变量。
  • 混合异步/同步:核心稳定性优先于I/O加速。
  • Pgwire兼容性,不复制PostgreSQL内部机制。
  • 无业务逻辑的数据引擎,确保纯粹性和可测试性。

— Editorial Team

Advertisement 728x90

继续阅读