READ COMMITTED vs REPEATABLE READ
Você já teve um bug onde os dados pareciam mudar “sozinhos” no meio do seu código? Isso pode ser falta de compreensão sobre os Níveis de Isolamento do SQL. Vamos focar nos dois mais usados: READ COMMITTED e REPEATABLE READ.
O Equilíbrio entre Corretude e Performance
Em um mundo perfeito, todas as transações seriam isoladas (Serializable). Mas isso travaria o banco de dados. Por isso, os bancos permitem escolher quão “isolado” você quer estar.
1. READ COMMITTED (Padrão do PostgreSQL/Oracle)
Uma transação só vê dados que já foram confirmados (commited) por outras transações.
- Evita: Dirty Reads (ler dados “sujos” que podem sofrer rollback).
- Problema: Non-Repeatable Reads. Se você ler o saldo do usuário no início do método e ler de novo 2 segundos depois (dentro da mesma transação), o valor pode ter mudado porque outra transação fez um commit no meio do caminho.
2. REPEATABLE READ (Padrão do MySQL/InnoDB)
Garante que, se você ler um registro, ele será o mesmo até o fim da sua transação, não importa o que aconteça fora dela.
- Evita: Non-Repeatable Reads. O banco cria um “snapshot” (versão) dos dados para você.
- Problema: Phantom Reads. Você pode ver novas linhas inseridas por outras transações que atendem ao seu critério de busca (embora o InnoDB do MySQL mitigue isso com Next-Key Locks).
Exemplo Visual
- Transação A começa e lê Saldo = 100.
- Transação B começa, muda Saldo para 200 e faz Commit.
- Transação A lê o saldo novamente.
- No
READ COMMITTED: Verá 200. - No
REPEATABLE READ: Verá 100.
- No
Qual usar no Spring?
Você pode definir o nível via anotação:
1
2
@Transactional(isolation = Isolation.REPEATABLE_READ)
public void processAudit() { ... }
Dica: A maioria das aplicações web funciona perfeitamente com READ COMMITTED. O REPEATABLE READ é mais seguro para processos de auditoria ou relatórios financeiros onde a consistência interna da transação é vital, mas ele consome mais recursos do banco e pode gerar mais Deadlocks.
Uma Pergunta para sua Próxima Transação
Você realmente precisa do isolamento REPEATABLE READ para esse fluxo, ou está apenas aceitando o padrão do seu banco de dados (como no caso do MySQL)? Muitas vezes, bugs de concorrência e deadlocks em produção são causados por níveis de isolamento excessivamente rigorosos para casos de uso simples. Ao projetar seu próximo serviço, questione: qual é o custo aceitável de uma leitura inconsistente versus o custo de travar o banco para garantir a perfeição?