针对 DuckDB 数据库的 Jepsen 测试。在本地运行,而不是在远程集群上。该测试会生成一组本地进程,它们打开本地的 DuckDB 文件,并通过标准输入/标准输出与其交互。
这是一个早期原型。它能启动、运行事务、检查正确性并报告错误,但我不确定这些错误是否真实存在。
你需要一个 JDK(21+)、Git、Gnuplot、Graphviz,以及 Leiningen。与大多数 Jepsen 测试不同,此测试完全在本地运行;你不需要集群机器、SSH 密钥等。
sudo apt install openjdk leiningen gnuplot graphviz
brew install openjdk leiningen gnuplot graphviz
要运行测试,请尝试:
lein run test
DuckDB(我猜测)默认提供强快照隔离(Strong SI),这也是测试所检查的内容。不过,它确实允许 G2-item,这违反了可重复读(Repeatable Read)。为了演示这一点,请尝试:
lein run test --time-limit 10 --expected-consistency-model serializable --max-writes-per-key 8
我们要求测试十秒钟,以查找可串行化(Serializability)的违规情况,并且(为了生成小巧且可读的示例)每个键只写入 8 个元素。G2-item 的示例应该可以在 store/latest/elle/G2-item 中找到。
有几个调节选项可用。各种选项的帮助可通过 lein run test --help 获取。
测试结果会写入 store/<test-name>/<date>/,并符号链接为 store/latest。每个测试目录都是自包含的;你可以复制它、打包成 tar 归档、稍后分析、删除等。你也可以运行一个 Web 服务器来浏览结果。
lein run serve
REPL 可用;请参见 lein repl。
测试框架位于此目录下;其项目文件是 project.clj,源代码位于 src/ 等。
测试框架运行一个独立的程序,即“本地节点”(local node),该节点嵌入 DuckDB 库并对其执行事务。测试框架为给定的工作负载生成随机事务,通过 HTTP 将它们提交给本地节点,并记录这些事务的结果,最后检查各种事务异常。我们使用 Elle 检查器(https://github.com/jepsen-io/elle)来查找强快照隔离(Strong Snapshot Isolation)。
本地节点有一个小型 HTTP 服务器,它接收来自测试框架的抽象事务(例如“读取键 x,然后将 y 设置为 5”),并将它们转换为针对 DuckDB JDBC 驱动程序执行的事务。
我们可以注入一种故障:进程杀死。
我们有两个工作负载。
第一个是 append,它运行向列表追加唯一整数并读取列表内容的事务。每个列表位于单行中,分布在多个表上。列表通过主键或未索引的二级键来标识。列表要么编码为文本字段,要么编码为 DuckDB INTEGER[] 列表。变更是通过 INSERT ON CONFLICT UPDATE 或 MERGE INTO 完成的。
第二个是 fkey-register,它对整数寄存器进行读写。在 DuckDB 中,我们将这些寄存器存储在两个表中。一个 逻辑 表将键映射到物理 ID,并带有外键。一个 物理 表将物理 ID 映射到值。我们使用简单的 JOIN 来读取。写操作要么通过更新物理行,要么通过创建新的物理行并更改逻辑指针来指向它。我今天刚刚让这个工作负载启动;它能运行,但还不完善。
版权所有 © 2026 Jepens, LLC
本程序及其随附材料根据 Eclipse 公共许可证 2.0 提供,该许可证可在 https://www.eclipse.org/legal/epl-2.0 获取。
本源代码也可能在满足 Eclipse 公共许可证 2.0 中规定的此类可用性条件时,根据以下二级许可证提供:GNU 通用公共许可证(由自由软件基金会发布),许可证版本 2 或(根据您的选择)任何更高版本,并附带 GNU 类路径例外,该例外可在 https://www.gnu.org/software/classpath/license.html 获取。