fundamentos·trail14·beginner
Transações e isolation levels: ACID sem decoreba
⏱ 15 min·⭐ 75 XP
ACID é a garantia que diferencia um banco de dados de um arquivo de texto. Atomicidade, Consistência, Isolamento, Durabilidade — não são decoreba, são propriedades com implementação concreta que você precisa entender para não introduzir bugs de concorrência sutis.
ACID: o que cada propriedade garante
-- Atomicidade: tudo ou nada
BEGIN;
UPDATE contas SET saldo = saldo - 100 WHERE id = 1; -- debita Alice
UPDATE contas SET saldo = saldo + 100 WHERE id = 2; -- credita Bob
-- Se o segundo UPDATE falhar, o primeiro é REVERTIDO automaticamente
COMMIT; -- ambos ou nenhum
-- Consistência: constraints são verificadas no COMMIT
BEGIN;
UPDATE contas SET saldo = saldo - 1000 WHERE id = 1;
-- CHECK (saldo >= 0) é violado → ROLLBACK automático ao tentar COMMIT
COMMIT;
-- Isolamento: transações concorrentes não se veem (depende do nível)
-- Ver seção de Isolation Levels abaixo
-- Durabilidade: após COMMIT, dado está no disco (WAL garante)
-- PostgreSQL usa Write-Ahead Log: toda mudança vai para WAL antes do heap
-- Em caso de crash, recovery reproduz o WAL
-- synchronous_commit = on (default): COMMIT espera WAL estar em discoIsolation Levels: o trade-off consistência × performance
| Nível | Dirty Read | Non-Repeatable Read | Phantom Read | Anomalias seriais |
|---|---|---|---|---|
| Read Uncommitted | Possível* | Possível | Possível | Possível |
| Read Committed (padrão PG) | Impossível | Possível | Possível | Possível |
| Repeatable Read | Impossível | Impossível | Impossível* | Possível |
| Serializable | Impossível | Impossível | Impossível | Impossível |
NívelRead Uncommitted
Dirty ReadPossível*
Non-Repeatable ReadPossível
Phantom ReadPossível
Anomalias seriaisPossível
NívelRead Committed (padrão PG)
Dirty ReadImpossível
Non-Repeatable ReadPossível
Phantom ReadPossível
Anomalias seriaisPossível
NívelRepeatable Read
Dirty ReadImpossível
Non-Repeatable ReadImpossível
Phantom ReadImpossível*
Anomalias seriaisPossível
NívelSerializable
Dirty ReadImpossível
Non-Repeatable ReadImpossível
Phantom ReadImpossível
Anomalias seriaisImpossível
-- Alterar isolation level para uma transação:
BEGIN TRANSACTION ISOLATION LEVEL REPEATABLE READ;
-- ... operações ...
COMMIT;
-- Ou para a sessão inteira:
SET SESSION CHARACTERISTICS AS TRANSACTION ISOLATION LEVEL SERIALIZABLE;
-- Exemplo de Non-Repeatable Read (Read Committed):
-- T1: BEGIN; SELECT saldo FROM contas WHERE id=1; → retorna 1000
-- T2: BEGIN; UPDATE contas SET saldo=500 WHERE id=1; COMMIT;
-- T1: SELECT saldo FROM contas WHERE id=1; → retorna 500 (mudou!)
-- Com Repeatable Read, T1 veria 1000 na segunda leitura
-- Serialization Anomaly (detectada pelo Serializable PG):
-- T1: SELECT SUM(quantidade) FROM estoque; → 100
-- T2: SELECT SUM(quantidade) FROM estoque; → 100
-- T1: INSERT INTO movimentos (tipo, qtd) VALUES ('entrada', 50) WHERE 100 < 200;
-- T2: INSERT INTO movimentos (tipo, qtd) VALUES ('saida', 100) WHERE 100 >= 50;
-- Ambas commitam — mas qualquer execução serial teria comportamento diferente!
-- Serializable aborta uma delas com: ERROR: could not serialize access✅
Guia prático: use Read Committed (padrão) para operações CRUD simples. Use Repeatable Read para relatórios que precisam de snapshot consistente. Use Serializable quando a lógica tem read-modify-write complexo. Use SELECT FOR UPDATE SKIP LOCKED para filas de trabalho. Nunca faça read-modify-write sem transação em sistemas concorrentes.
💡
Próximo: Normalização e modelagem — 1NF, 2NF, 3NF e quando desnormalizar intencionalmente.
Discussão
Carregando…