ChaosSQL

Catálogo de Concorrência

Cenários Canônicos & Mitigações

Explore 10 cenários de falhas de concorrência baseados em pesquisas acadêmicas de isolamento e casos reais de sistemas financeiros e distribuídos.

A3

Venda Excessiva de Inventário (Oversell)

Checkouts simultâneos reservam o último item disponível devido a anti-dependências de predicado (leituras fantasmas).

Checkouts simultâneos reservam o último item disponível devido a anti-dependências de predicado (leituras fantasmas).

Schema e dados iniciais

schema.sql & seed.sql
-- Schema
CREATE TABLE products (
    id INT PRIMARY KEY,
    name TEXT NOT NULL,
    stock INT NOT NULL
);

-- Seed
INSERT INTO products VALUES (1, 'RTX 5090 GPU', 1);

Carga concorrente (chaos.yaml)

chaos.yaml
version: "1.0"
name: "inventory_oversell"
operations:
  - name: "checkout"
    steps:
      - "SELECT stock FROM products WHERE id = 1 -> avail"
      - "UPDATE products SET stock = {avail - 1} WHERE id = 1 AND {avail > 0}"
invariants:
  - name: "stock_non_negative"
    query: "SELECT stock FROM products WHERE id = 1;"
    assert: "stock >= 0"

Por que a invariante quebra

Ambos os workers avaliam {avail > 0} como verdadeiro antes que qualquer commit atualize o estoque físico em disco, levando o inventário a -1.

T1 ──(rw)──► T2 ──(ww)──► T1

Delta debugging reduz 30 operações às 2 que causam a falha.

Correção em produção

Guarded Decrement Atômico com Verificação de Linhas Afetadas

A condição de guarda {avail > 0} avaliada na memória da aplicação é obsoleta (stale) no momento em que a escrita chega ao disco. Ao mover a verificação diretamente para o WHERE da instrução UPDATE (AND stock >= 1), o motor de banco garante a avaliação atômica do predicado e o bloqueio de escrita sobre a linha. Se múltiplos clientes tentarem comprar a última unidade simultaneamente, exatamente um decrementará o estoque para 0 e os demais receberão 0 linhas afetadas.

✓ PostgreSQL✓ SQLite✓ MySQL (InnoDB)

PostgreSQL, SQLite, MySQL (InnoDB)

remediation_fix.sql
-- Decremento Atômico Protegido no Banco de Dados
UPDATE products 
SET stock = stock - 1 
WHERE id = 1 AND stock >= 1;

-- No código de aplicação (Go / Node):
-- Verificar se rows_affected == 1.
-- Se rows_affected == 0, retornar ErrProdutoEsgotado sem prosseguir para pagamento.