Teoria
Teoria Formal & Fundamentação Matemática
O embasamento científico rigoroso do ChaosSQL: Condições de Conflito de Bernstein, Teorema da Serializabilidade por Conflito (CSR), agendamento probabilístico PCT com Teorema de Burckhardt, minimização com Zeller ddmin e verificação de linearizabilidade estilo Elle.
1. Modelo Formal de Transações e Histórias de Execução
O ChaosSQL fundamenta sua análise na teoria formal clássica de banco de dados estabelecida por Bernstein, Goodman, Papadimitriou e Adya.
Definição Formal de Transação
Uma transação Ti é definida matematicamente como uma tupla ordenada:
Ti = (Oi, <i)
Onde:
- Oi é um conjunto finito de operações atômicas de leitura ri[x], escrita wi[x], commit ci ou abort ai, acessando entidades de dados x ∈ D.
- <i é uma ordem estrita parcial sobre Oi que reflete o fluxo determinístico do programa da transação.
- Existe exatamente uma operação terminal ti ∈ {ai, ci}, que é o elemento maximal sob <i.
Definição Formal de História (Schedule)
Uma história de execução concorrente S sobre um conjunto finito de transações T = {T1, T2, …, Tn} é uma ordem parcial S = (bigcupi=1n Oi, <S) que satisfaz:
- bigcupi=1n <i ⊆ <S (preserva a ordem interna de instruções de cada transação).
- Para quaisquer duas operações conflitantes oi, oj ∈ S (onde i ≠ j), ou oi <S oj ou oj <S oi.
2. Condições de Conflito de Bernstein & Teorema CSR
Condição de Conflito de Bernstein (1966)
Duas operações oi, oj ∈ S pertencentes a transações distintas (i ≠ j) estão em conflito direto se e somente se acessam a mesma entidade de dados x ∈ D e pelo menos uma delas é uma operação de mutação (w):
Conflict(oi, oj) ⟺ (target(oi) = target(oj) = x) ∧ (oi is w ∨ oj is w)
Grafo de Serialização Direta (Adya Dependency Graph)
Dado um schedule de execução S, o Grafo de Serialização SG(S) = (V, E) é um dígrafo onde:
- Os vértices V = T correspondem ao conjunto de transações comitadas.
- Existe uma aresta direcionada (Ti → Tj) ∈ E se e somente se existe oi ∈ Ti e oj ∈ Tj tais que oi <S oj e Conflict(oi, oj).
As Três Relações Fundamentais de Dependência (Atul Adya, 1999)
- Dependência de Leitura (wr - Read Dependency): Ti —wr→ Tj se Ti grava uma versão de x e Tj subsequentemente lê essa mesma versão.
- Dependência de Sobrescrita (ww - Overwrite Dependency): Ti —ww→ Tj se Ti grava uma versão de x e Tj subsequentemente sobrescreve x.
- Anti-Dependência (rw - Anti-Dependency): Ti —rw→ Tj se Ti lê uma versão de x e Tj subsequentemente grava uma nova versão de x, tornando a leitura de Ti desatualizada.
Teorema Fundamental da Serializabilidade por Conflito (CSR)
A presença de qualquer ciclo direcionado (T1 → T2 → … → T1) prova que a execução é semanticamente inconsistente e não possui equivalente serial.
3. Agendamento Probabilístico PCT-SQL (Burckhardt & Musuvathi)
Testes de concorrência ingênuos falham devido à explosão combinatória. Para n transações executando m passos cada, o número de intercalações possíveis Ω cresce fatorialmente:
|Ω| = ((n · m)!)⁄(m!)n
Para apenas 5 transações de 3 passos, existem 168.168.000 intercalações possíveis. A chance de acertar a troca de contexto exata por pura aleatoriedade é inferior a 10-6.
Teorema do Limite Inferior de Burckhardt (ASPLOS 2010)
Burckhardt e Musuvathi provaram que, se um bug de concorrência requer uma profundidade de agendamento d (número de restrições de prioridade ou trocas de contexto críticas para disparar), o algoritmo Probabilistic Concurrency Testing (PCT) o encontra em uma única rodada com pelo menos esta probabilidade:
ℙ(Detecção) ≥ 1⁄(n · kd-1)
Onde n é o número de threads concorrentes e k é o total de passos executados.
Aplicação Prática em Bancos de Dados Relacionais
- Estudos empíricos seminais (Lu et al., ASPLOS) demonstram que ~96% dos bugs de concorrência reais possuem profundidade d = 1 ou d = 2 (Lost Update requer d=1; Write Skew requer d=2).
- Para d = 2, a probabilidade de detecção por execução é ℙ ≥ 1⁄(n · k). Em um teste com 4 workers e 25 passos (n=4, k=25), ℙ ≥ 1⁄100 = 1%.
- Em uma bateria curta de R = 300 rodadas:
ℙ(Encontrar o Bug em R Rodadas) = 1 - (1 - 1⁄100)300 ≈ 1 - e-3 ≈ 95.02%
4. Minimização com Andreas Zeller Delta-Debugging (ddmin)
Definição Formal de 1-Minimalidade
Seja C = ⟨ op1, op2, …, opN ⟩ a sequência ordenada de operações agendadas que dispara uma falha de invariante test(C) = FAIL.
Uma subsequência C* ⊆ C é dita 1-Minimal se e somente se:
test(C*) = FAIL ∧ ∀ op ∈ C*: test(C* ∖ {op}) = PASS
A Implementação do ddmin no ChaosSQL
O ChaosSQL executa cada subsequência candidata contra um banco recém-reinicializado e só a mantém quando ela reproduz a mesma assinatura de falha: status violation na mesma invariante. Um candidato que termina com outro status, como um erro de execução por FOREIGN KEY constraint failed causado pela remoção da operação que criou o registro pai, não conta como reprodução e é descartado.
- Os replays são memoizados, então uma subsequência já testada nunca é executada duas vezes.
- Depois que o ddmin converge, uma auditoria final remove cada operação restante uma vez e confirma que a falha desaparece, o que estabelece a 1-minimalidade.
- O shrinker não calcula dependências de dados entre operações; ele depende da checagem de assinatura para rejeitar candidatos que quebram a integridade referencial.
5. Linearizabilidade e Observações de Caixa-Preta (Elle)
Inspirado na metodologia de Kyle Kingsbury (Jepsen) e Peter Alvaro (VLDB 2020), o ChaosSQL infere anomalias estritamente a partir do histórico observável de operações do cliente (leituras, escritas e retornos). Não há necessidade de instrumentação interna no código fonte do banco de dados, tornando o ChaosSQL universalmente compatível com qualquer motor relacional compatível com SQL.