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.
Ciclo de Deadlock & Recuperação
Dois workers de transferência bloqueiam contas em ordem inversa, induzindo um deadlock no grafo de espera (WFG).
Dois workers de transferência bloqueiam contas em ordem inversa, induzindo um deadlock no grafo de espera (WFG).
Schema e dados iniciais
-- Schema
CREATE TABLE accounts (
id INT PRIMARY KEY,
balance INT NOT NULL
);
-- Seed
INSERT INTO accounts VALUES (1, 500), (2, 500);Carga concorrente (chaos.yaml)
version: "1.0"
name: "deadlock_cycle_recovery"
operations:
- name: "transfer_1_to_2"
steps:
- "SELECT balance FROM accounts WHERE id = 1 -> b1"
- "UPDATE accounts SET balance = balance - 100 WHERE id = 1"
- "UPDATE accounts SET balance = balance + 100 WHERE id = 2"
- name: "transfer_2_to_1"
steps:
- "SELECT balance FROM accounts WHERE id = 2 -> b2"
- "UPDATE accounts SET balance = balance - 100 WHERE id = 2"
- "UPDATE accounts SET balance = balance + 100 WHERE id = 1"
invariants:
- name: "total_balance_exact"
query: "SELECT sum(balance) AS total FROM accounts;"
assert: "total == 1000"Por que a invariante quebra
T1 trava a Conta 1 e requisita trava na Conta 2. Concorrentemente, T2 trava a Conta 2 e requisita trava na Conta 1. A espera mútua induz um ciclo no Wait-For Graph (WFG).
T1 ──(waits)──► T2 ──(waits)──► T1Delta debugging reduz 15 operações às 2 que causam a falha.
Correção em produção
Ordenação Canônica Determinística de Bloqueios (Lock Ordering)
Deadlocks ocorrem quando diferentes transações disputam os mesmos registros em ordens inversas (T1: 1 depois 2; T2: 2 depois 1). A mitigação canônica consiste em estabelecer um protocolo estrito de ordenação hierárquica de recursos antes de adquirir qualquer bloqueio (ex: travar sempre pelo menor ID primeiro). Com ordenação canônica garantida na camada de repositório, ciclos no Wait-For Graph tornam-se matematicamente impossíveis de se formarem.
PostgreSQL (Code 40P01), MySQL (Error 1213), SQLite
-- Ordenação Padronizada de Locks pelo Menor ID
-- Na aplicação:
-- first_id = MIN(conta_a, conta_b)
-- second_id = MAX(conta_a, conta_b)
BEGIN;
-- Bloquear sempre os recursos na mesma ordem canônica crescente:
SELECT id, balance FROM accounts WHERE id = :first_id FOR UPDATE;
SELECT id, balance FROM accounts WHERE id = :second_id FOR UPDATE;
UPDATE accounts SET balance = balance - 100 WHERE id = :origem;
UPDATE accounts SET balance = balance + 100 WHERE id = :destino;
COMMIT;