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 Anti-Dependência em Bilheteria (G2)
Reservas de ingressos geram conflitos fantasmas entre predicados de assentos sob Snapshot Isolation.
Reservas de ingressos geram conflitos fantasmas entre predicados de assentos sob Snapshot Isolation.
Schema e dados iniciais
-- Schema
CREATE TABLE seats (
id INT PRIMARY KEY,
section TEXT NOT NULL,
seat_no INT NOT NULL,
reserved_by TEXT
);
-- Seed
INSERT INTO seats VALUES (1, 'VIP', 101, NULL), (2, 'VIP', 102, NULL);Carga concorrente (chaos.yaml)
version: "1.0"
name: "ticket_anti_dependency_g2"
operations:
- name: "book_adjacent_left"
steps:
- "SELECT count(*) AS reserved FROM seats WHERE section = 'VIP' AND reserved_by IS NOT NULL -> c"
- "UPDATE seats SET reserved_by = 'Fan_A' WHERE id = 1 AND {c == 0}"
- name: "book_adjacent_right"
steps:
- "SELECT count(*) AS reserved FROM seats WHERE section = 'VIP' AND reserved_by IS NOT NULL -> c"
- "UPDATE seats SET reserved_by = 'Fan_B' WHERE id = 2 AND {c == 0}"
invariants:
- name: "max_one_seat_rule"
query: "SELECT count(*) AS reserved FROM seats WHERE section = 'VIP' AND reserved_by IS NOT NULL;"
assert: "reserved <= 1"Por que a invariante quebra
Ciclo de anti-dependência de predicado: T1 verifica se algum assento VIP está reservado (encontra 0) e reserva o assento 1. T2 simultaneamente verifica assentos VIP (encontra 0) e reserva o assento 2. Ambos comitam, violando a exclusividade do setor.
T1 ──(rw)──► T2 ──(rw)──► T1Delta debugging reduz 20 operações às 2 que causam a falha.
Correção em produção
Restrição de Unicidade Estrutural e Locks de Predicado Serializáveis
Ciclos G2 ocorrem quando consultas de agregação ou intervalos checam a existência de registros através de predicados (COUNT(*) WHERE ...). Sob Snapshot Isolation, as transações não bloqueiam predicados ausentes. A adição de uma restrição UNIQUE a nível de schema converte a corrida silenciosa em um erro determinístico de integridade de índice, enquanto SELECT ... FOR UPDATE ou SSI serializam a reserva de forma infalível.
PostgreSQL, MySQL, SQLite
-- 1. Restrição de Chave Única Composta para Garantir Atomicidade de Índice
ALTER TABLE seats
ADD CONSTRAINT uq_section_reservation UNIQUE (section, seat_no);
-- 2. Predicate Lock com SELECT FOR UPDATE ou SSI
BEGIN;
SELECT id FROM seats
WHERE section = 'VIP' AND reserved_by IS NULL
LIMIT 1 FOR UPDATE;
UPDATE seats SET reserved_by = 'Fan_A' WHERE id = :seat_id;
COMMIT;