Hotdry.
systems

FrankenSQLite:通过 MVCC 和 WAL 实现 Rust SQLite 的并发写

Rust 重写的 SQLite,支持页级 MVCC 和专用 WAL 通道的多写者并发,提供工程参数、配置清单与监控要点。

在嵌入式数据库应用中,SQLite 的单写者限制常常成为高并发场景下的瓶颈。传统 SQLite 即使启用 WAL 模式,也仅允许一个写事务同时进行,其他写操作会遭遇 SQLITE_BUSY 错误,导致应用层需实现重试或序列化处理。FrankenSQLite 作为纯 Rust 重实现的 SQLite,通过页级 MVCC(多版本并发控制)和每个写者的专用 WAL 通道,彻底消除这一限制,支持多个并发写者(如最多 8 个)同时操作,而不阻塞读者或无关写者。

MVCC 机制:页级版本隔离

FrankenSQLite 的核心在于页级 MVCC。每笔事务启动时捕获一个快照(snapshot),读取特定时刻的页版本。写事务不修改原页,而是创建 shadow page(影子页)副本,仅修改副本并向上链接树结构。这确保读者始终看到一致视图,而写者间仅在触及相同页时才可能冲突。

具体实现中,每个页(4KB)维护版本链,版本通过提交序列号(commit sequence number)决定可见性:若版本号高于事务快照,则不可见。这一简单规则支撑整个系统正确性。例如,事务 T1 读取页 P 的版本 V1,T2 同时创建 V2;T1 继续看到 V1,T2 提交后新事务可见 V2。网站演示显示,8 个写者并行操作不同页集,无锁竞争。

SSI(可串行快照隔离)进一步处理冲突:维护读写依赖图,commit 时检测危险循环,若形成则中止 pivot 事务。智能合并梯度(Safe Merge Ladder)优先尝试重执行、XOR delta 合并或字节级融合,仅最后才 abort/retry,大幅降低重试率。

WAL 通道:独立写日志

传统 SQLite WAL 虽改善读并发,但写仍串行通过单一 WAL 文件。FrankenSQLite 为每个写者分配独立 WAL lane(通道),允许多路并发 append。读者通过共享内存的 lock-free 结构定位最新页版本,支持 checkpoint 时将 frame 刷回主文件。

崩溃恢复类似标准 WAL:丢弃未提交 frame,重放已提交。双存储模式下,还支持原生 append-only 格式,交织数据页与 RaptorQ fountain codes,实现自愈。

“FrankenSQLite 赋予每个写者私有页版本,仅触及页集,无 SQLITE_BUSY 错误。” 这一设计在负载下展现 8x 吞吐提升。

工程落地参数与配置清单

部署 FrankenSQLite 时,聚焦并发参数调优,确保稳定高吞吐。

  1. 并发写者上限:默认 8,可通过 PRAGMA concurrent_writers=12 调整。单进程 Rust 应用设 4-8,多进程设更高,但监控内存(每个 writer ~ 额外 10-20% buffer)。

  2. WAL 配置

    • PRAGMA wal_autocheckpoint=1000(页数),lane 达阈值自动 checkpoint。
    • PRAGMA synchronous=NORMAL,平衡耐久与性能;生产用 FULL。
    • Per-lane 大小:建议 1GB,主文件 <100GB 时。
  3. Buffer Pool

    • PRAGMA cache_size=10000(页),~40MB。混合负载用 Cooling Protocol:热页驻留,冷页渐退。
    • mmap_size=0 禁用 mmap,避免多进程冲突。
  4. MVCC 参数

    • vacuum_frequency=1000(提交),GC 旧版本。
    • ssi_timeout=500ms,冲突检测超时时 abort。

Rust 集成示例:

use fsqlite::Connection;
let conn = Connection::open("data.db")?;
conn.execute("PRAGMA journal_mode=WAL; PRAGMA concurrent_writers=8;", [])?;
let mut stmt = conn.prepare("BEGIN CONCURRENT; INSERT INTO t VALUES (?); COMMIT;")?;
stmt.bind(1, 42)?; stmt.next()?;

多线程:Connection Send+Sync,支持 tokio::spawn 并发写。

监控与回滚策略

内置事务遥测(PRAGMA transaction_stats)追踪 BEGIN/COMMIT 耗时、读写页数、冲突率。Chrome trace JSON 导出可视化。警报阈值:

  • 冲突率 >5%:降 concurrent_writers。
  • WAL >80%:增 autocheckpoint。
  • Txn 延迟 P99 >100ms:查 anti-pattern(如长锁持)。

回滚策略:

  1. 指数退避重试(初始 10ms,max 1s)。
  2. 读写分离:写热表用专用 pool。
  3. 降级单写:负载峰值时 PRAGMA concurrent_writers=1。

压力测试:sysbench/tpc-c 模拟,预期写 QPS 提升 4-8x vs 原 SQLite WAL。

FrankenSQLite 26 crates 模块化,仅拉取 mvcc/wal 层即用。零 unsafe 代码,编译时拒类型混淆,生产级安全。

资料来源:

查看归档