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.
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
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)
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)──► T1Delta 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)
-- 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.