
Framework de teste de correção transacional baseado em Jepsen para DuckDB, detectando anomalias de isolamento como violações G2-item e SSI por meio de cargas de trabalho aleatórias e do verificador Elle.
Testes Jepsen para a base de dados DuckDB. Executa localmente, ao invés de em um cluster remoto. O teste cria uma coleção de processos locais que abrem um arquivo DuckDB localmente e interage com eles via STDIN/STDOUT.
Este é um protótipo inicial. Ele liga, executa transações, verifica sua correção e reporta bugs, mas não tenho certeza se esses bugs são reais.
Você precisará de um JDK (21+), Git, Gnuplot, Graphviz, além do Leiningen. Ao contrário da maioria dos testes Jepsen, este é executado inteiramente localmente; você não precisa de um cluster de máquinas, chaves SSH, etc.
sudo apt install openjdk leiningen gnuplot graphviz
brew install openjdk leiningen gnuplot graphviz
Para executar um teste, tente:
lein run test
O DuckDB fornece (suspeito) Strong SI por padrão, e é isso que o teste verifica. No entanto, ele permite G2-item, o que é uma violação do Repeatable Read. Para demonstrar isso, tente:
lein run test --time-limit 10 --expected-consistency-model serializable --max-writes-per-key 8
Estamos solicitando testar por dez segundos, para procurar violações de Serializabilidade, e (para gerar exemplos pequenos e legíveis), escrever apenas 8 elementos por chave. Exemplos de G2-item devem estar disponíveis em store/latest/elle/G2-item.
Existem várias opções de ajuste disponíveis. A ajuda para as várias opções está disponível através de lein run test --help.
Os resultados dos testes são escritos em store/<test-name>/<date>/, e com link simbólico para store/latest. Cada um desses diretórios de teste é autocontido; você pode copiá-lo, compactá-lo, analisá-lo posteriormente, deletá-lo, e assim por diante. Você também pode executar um servidor web para navegar pelos resultados.
lein run serve
Um REPL está disponível; veja lein repl.
O harness de teste reside neste diretório; seu arquivo de projeto é project.clj, seu código fonte está em src/, e assim por diante.
O harness de teste executa um programa separado, o "nó local", que incorpora a biblioteca DuckDB e realiza transações contra ela. O harness de teste gera transações aleatórias para uma determinada carga de trabalho, submete-as via HTTP ao nó local e registra os resultados dessas transações, verificando no final várias anomalias transacionais. Procuramos por Strong Snapshot Isolation, usando o verificador Elle (https://github.com/jepsen-io/elle).
O nó local possui um pequeno servidor HTTP que recebe transações abstratas (por exemplo, "ler chave x, depois definir y para 5") do harness de teste e as traduz em transações executadas contra o driver JDBC do DuckDB.
Podemos injetar um tipo de falha: mortes de processo.
Temos duas cargas de trabalho.
A primeira, append, executa transações que anexam inteiros únicos a listas e lê o conteúdo dessas listas. Cada lista vive em uma única linha, espalhada por várias tabelas. As listas são identificadas por chave primária ou por uma chave secundária não indexada. As listas são codificadas como campos de texto ou como listas DuckDB INTEGER{ ]. A mutação é feita com INSERT ON CONFLICT UPDATE ou MERGE INTO.
A segunda, fkey-register, realiza leituras e escritas de registros inteiros. No DuckDB, armazenamos esses registros em duas tabelas. Uma tabela lógica mapeia chaves para IDs físicos, com uma chave estrangeira. Uma tabela física mapeia IDs físicos para valores. Usamos um JOIN direto entre as duas para ler. As escritas são realizadas atualizando a linha física ou criando uma nova linha física e alterando o ponteiro lógico para ela. Acabei de fazer esta carga de trabalho ligar hoje; ela funciona, mas ainda não está polida.
Copyright © 2026 Jepens, LLC
Este programa e os materiais acompanhantes são disponibilizados sob os termos da Eclipse Public License 2.0 que está disponível em https://www.eclipse.org/legal/epl-2.0.
Este Código Fonte também pode ser disponibilizado sob as seguintes Licenças Secundárias quando as condições para tal disponibilidade estabelecidas na Eclipse Public License, v. 2.0 forem satisfeitas: GNU General Public License conforme publicada pela Free Software Foundation, seja a versão 2 da Licença ou (a seu critério) qualquer versão posterior, com a Exceção GNU Classpath que está disponível em https://www.gnu.org/software/classpath/license.html.