Pular para o conteúdo

Arquitetura de software · Dados · 8 min de leitura

Transações e níveis de isolamento

ACID promete que uma transação acontece por inteiro ou não acontece — mas o quanto ela enxerga das outras depende do nível de isolamento, e cada nível deixa passar anomalias diferentes.

Conta → Transação A1Conta → Transação B2Transação A → A grava 703Transação B → B grava 504B grava 50 → Saldo final 50Transação A — lê saldo 100Transação Alê saldo 100Transação B — lê saldo 100Transação Blê saldo 100Conta — saldo = 100Contasaldo = 100A grava 70 — saque de 30A grava 70saque de 30B grava 50 — saque de 50B grava 50saque de 50Saldo final 50 — deveria ser 20Saldo final 50deveria ser 20

Arraste para o lado para ver o diagrama inteiro.

Ler, calcular na aplicação e gravar o resultado é a receita da atualização perdida; a correção é deixar o banco fazer a conta ou travar a linha.

ACID em uma frase cada

  • Atomicidade: tudo ou nada — um erro no meio desfaz o que foi feito.
  • Consistência: as regras (chaves, CHECK, únicos) valem antes e depois.
  • Isolamento: transações simultâneas não se atrapalham — até certo ponto.
  • Durabilidade: depois do COMMIT, o dado sobrevive a uma queda (graças ao log de escrita antecipada).

As anomalias

  • Leitura suja: ver dado de outra transação que ainda não confirmou.
  • Leitura não repetível: ler a mesma linha duas vezes e obter valores diferentes.
  • Fantasma: repetir uma consulta e aparecerem linhas novas.
  • Atualização perdida: o caso do diagrama.
  • Write skew: duas transações leem a mesma condição (“há outro médico de plantão”), cada uma altera uma linha diferente e juntas quebram a regra.

Os níveis na prática

  • Read Committed — padrão do PostgreSQL: cada comando vê o que já foi confirmado. Sem leitura suja; o resto pode acontecer.
  • Repeatable Read — padrão do MySQL/InnoDB; no PostgreSQL é snapshot isolation: a transação toda vê uma foto do início e detecta atualização perdida (erro de serialização), mas não write skew.
  • Serializable: o resultado equivale a rodar uma transação de cada vez. No PostgreSQL usa SSI e pode abortar transações — a aplicação precisa repetir quando receber erro de serialização.

Os nomes são os mesmos em todos os bancos, mas o comportamento varia; o projeto Hermitage testa isso banco a banco.

Receitas

  • Faça a conta no banco: UPDATE contas SET saldo = saldo - 30 WHERE id = 1 AND saldo >= 30.
  • Trave o que vai alterar: SELECT … FOR UPDATE dentro da transação.
  • Controle otimista: coluna versao e UPDATE … WHERE versao = 7; se nenhuma linha mudou, alguém chegou antes.
  • Transações curtas: nada de chamar API externa com a transação aberta.

No código: antes e depois

✗ AntesTypeScript
// Lê, calcula na aplicação e grava: duas requisições juntas perdem um saque.
const { rows } = await db.query('SELECT saldo FROM contas WHERE id = $1', [id]);
const novo = rows[0].saldo - valor;
if (novo < 0) throw new Error('saldo insuficiente');
await db.query('UPDATE contas SET saldo = $1 WHERE id = $2', [novo, id]);
✓ DepoisTypeScript
// Uma transação, e a conta feita pelo banco com a condição na mesma instrução.
await db.query('BEGIN');
try {
  const r = await db.query(
    'UPDATE contas SET saldo = saldo - $1 WHERE id = $2 AND saldo >= $1',
    [valor, id],
  );
  if (r.rowCount === 0) throw new Error('saldo insuficiente');
  await db.query('INSERT INTO lancamentos (conta_id, valor) VALUES ($1, $2)', [id, -valor]);
  await db.query('COMMIT');
} catch (e) {
  await db.query('ROLLBACK');
  throw e;
}

O UPDATE com saldo = saldo - $1 é atômico e a condição impede saldo negativo; o lançamento entra na mesma transação, então ou os dois acontecem ou nenhum.

Em resumo

Vantagens e custos

Vantagens
  • Níveis mais fortes eliminam classes inteiras de bugs.
  • Controle otimista não trava ninguém quando há pouca disputa.
Custos e riscos
  • Serializable aborta mais e exige retry.
  • FOR UPDATE cria filas e pode causar deadlock.
  • Transações longas seguram travas e versões antigas.

Perguntar à IA

Monte um prompt pronto sobre Transações e níveis de isolamento na sua linguagem e no seu caso, e abra num chat gratuito.

ChatGPT Claude Perplexity

O prompt vai para o site que você escolher. Não cole senhas, tokens nem dados reais de clientes. Para Gemini e outros, copie e cole.

Referências

Continue aprendendo

Todos os temas de arquitetura de software →