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.

A5A

Distorção de Leitura Financeira (Read Skew)

Uma consulta de auditoria observa uma transferência parcialmente aplicada, detectando uma discrepância espúria no patrimônio total.

Uma consulta de auditoria observa uma transferência parcialmente aplicada, detectando uma discrepância espúria no patrimônio total.

Schema e dados iniciais

schema.sql & seed.sql
-- Schema
CREATE TABLE accounts (
    id INT PRIMARY KEY,
    balance INT NOT NULL
);

-- Seed
INSERT INTO accounts VALUES (1, 1000), (2, 1000);

Carga concorrente (chaos.yaml)

chaos.yaml
version: "1.0"
name: "financial_read_skew"
operations:
  - name: "transfer_100"
    steps:
      - "UPDATE accounts SET balance = balance - 100 WHERE id = 1"
      - "UPDATE accounts SET balance = balance + 100 WHERE id = 2"
  - name: "audit_total"
    steps:
      - "SELECT balance FROM accounts WHERE id = 1 -> b1"
      - "SELECT balance FROM accounts WHERE id = 2 -> b2"
invariants:
  - name: "total_wealth_preserved"
    query: "SELECT sum(balance) AS total FROM accounts;"
    assert: "total == 2000"

Por que a invariante quebra

Sob READ COMMITTED, cada SELECT na transação de auditoria tira um snapshot isolado. A auditoria lê a conta 1 antes da transferência (-$100), mas lê a conta 2 após a transferência (+$100), observando $1000 + $1100 = $2100.

T1 ──(rw)──► T2 ──(wr)──► T1

Delta debugging reduz 25 operações às 3 que causam a falha.

Correção em produção

Isolamento REPEATABLE READ / SNAPSHOT para Transações de Auditoria

Sob READ COMMITTED, cada instrução SELECT cria uma nova fotografia temporal (snapshot). Se uma transação de transferência comitar entre a leitura da conta 1 e da conta 2, o relatório financeiro observará o estado de contas em momentos díspares do tempo. Ao elevar a transação de leitura para REPEATABLE READ (ou SNAPSHOT ISOLATION), o banco congela um único Point-in-Time Snapshot imutável no primeiro SELECT, garantindo consistência estrita de leitura sem necessidade de bloqueios.

✓ PostgreSQL✓ MySQL (InnoDB)✓ SQLite (WAL)

PostgreSQL, MySQL (InnoDB), SQLite (WAL)

remediation_fix.sql
-- Transação de Auditoria em REPEATABLE READ
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;

BEGIN;
-- Todas as consultas subsequentes leem a mesma fotografia temporal do banco:
SELECT balance AS bal1 FROM accounts WHERE id = 1;
-- Mesmo que a transferência ocorra e comite aqui no meio...
SELECT balance AS bal2 FROM accounts WHERE id = 2;
-- bal1 + bal2 sempre somará exatamente 2000!
COMMIT;