Entendendo Transações de Banco de Dados
Quando um usuário faz um pedido na sua plataforma, várias coisas acontecem ao mesmo tempo: o estoque diminui, um registro de pagamento é criado e uma entrada de pedido é salva. Se o servidor travar no meio do processo, você pode acabar com um cliente cobrado e nenhum pedido registrado. As transações de banco de dados existem especificamente para prevenir esse tipo de falha parcial.
Este artigo aborda o que são transações de banco de dados, como as propriedades ACID garantem confiabilidade, como os níveis de isolamento de transação controlam o acesso concorrente e como os bancos de dados modernos usam MVCC para fazer tudo isso funcionar de forma eficiente.
Pontos-Chave
- Uma transação de banco de dados agrupa múltiplas operações em uma única unidade de trabalho — ou todas têm sucesso ou todas são revertidas.
- As propriedades ACID (Atomicidade, Consistência, Isolamento, Durabilidade) definem as garantias de confiabilidade que as transações fornecem.
- O SQL define quatro níveis de isolamento, mas o comportamento real varia significativamente entre motores de banco de dados como PostgreSQL, MySQL e SQLite.
- O MVCC permite que bancos de dados modernos lidem com leituras e escritas concorrentes de forma eficiente, mantendo múltiplas versões de linhas em vez de depender de bloqueios pesados.
O Que É uma Transação de Banco de Dados?
Uma transação de banco de dados é uma sequência de operações tratadas como uma única unidade de trabalho. Ou todas as operações têm sucesso e as mudanças são confirmadas (committed), ou algo falha e tudo é revertido (rolled back) ao estado anterior.
Em SQL, uma transação básica se parece com isto:
BEGIN;
UPDATE accounts SET balance = balance - 500 WHERE id = 1;
UPDATE accounts SET balance = balance + 500 WHERE id = 2;
COMMIT;
Se algo falhar entre BEGIN e COMMIT, um ROLLBACK restaura o banco de dados ao seu estado antes do início da transação. A maioria dos bancos de dados também suporta SAVEPOINT para reversões parciais dentro de uma transação.
Propriedades ACID: O Que Elas Realmente Significam
ACID é o conjunto de garantias que tornam as transações confiáveis:
- Atomicidade — Todas as etapas têm sucesso, ou nenhuma tem. Sem atualizações parciais.
- Consistência — O banco de dados passa de um estado válido para outro. Restrições e regras são aplicadas.
- Isolamento — Transações concorrentes não interferem umas com as outras.
- Durabilidade — Uma vez confirmadas, as mudanças sobrevivem a falhas. Isso é tipicamente implementado via write-ahead logging (WAL).
A conformidade com ACID tem um custo de desempenho. Alguns sistemas permitem que você troque garantias estritas por velocidade, e é por isso que entender essas propriedades é importante ao projetar sua camada de dados.
Níveis de Isolamento de Transação Explicados
O isolamento é a mais sutil das quatro propriedades ACID. O SQL define quatro níveis de isolamento de transação padrão, cada um permitindo diferentes trade-offs entre consistência e concorrência:
| Nível de Isolamento | Leituras Sujas | Leituras Não Repetíveis | Leituras Fantasma |
|---|---|---|---|
| READ UNCOMMITTED | Possível | Possível | Possível |
| READ COMMITTED | Prevenida | Possível | Possível |
| REPEATABLE READ | Prevenida | Prevenida | Possível |
| SERIALIZABLE | Prevenida | Prevenida | Prevenida |
Importante: O comportamento real varia de acordo com o motor do banco de dados.
- PostgreSQL não implementa
READ UNCOMMITTED— ele silenciosamente o eleva paraREAD COMMITTED. Seu padrão éREAD COMMITTEDconforme documentado no guia oficial de níveis de isolamento. - MySQL (InnoDB) usa
REPEATABLE READcomo padrão. Ele utiliza gap locks em certos casos para reduzir leituras fantasma, mas o comportamento depende do nível de isolamento e do padrão de consulta, conforme descrito na documentação de isolamento do InnoDB. - SQLite usa um modelo de escritor único, o que significa que apenas uma transação de escrita pode ser executada por vez. Ele suporta os modos de transação
DEFERRED,IMMEDIATEeEXCLUSIVEem vez dos níveis de isolamento padrão, conforme descrito na documentação de transações do SQLite.
Não assuma comportamento idêntico entre bancos de dados. Sempre consulte a documentação do seu motor específico.
Discover how at OpenReplay.com.
Como o MVCC Torna o Isolamento Prático
A maioria dos bancos de dados relacionais modernos — incluindo PostgreSQL e MySQL (InnoDB) — implementam isolamento através de Multi-Version Concurrency Control (MVCC) em vez de bloqueios simples.
Com MVCC, as consultas veem um snapshot consistente dos dados, mas se esse snapshot é capturado por instrução ou por transação depende do nível de isolamento e do motor do banco de dados. Os escritores criam novas versões de linhas em vez de sobrescrevê-las. Os leitores não bloqueiam escritores, e escritores não bloqueiam leitores.
É por isso que o PostgreSQL pode atender cargas de trabalho com muitas leituras sem que os leitores fiquem constantemente esperando por bloqueios. O trade-off é que versões antigas de linhas se acumulam e devem ser limpas — no PostgreSQL, isso é tratado pelo processo VACUUM.
O MVCC é o que torna REPEATABLE READ e isolamento de snapshot práticos em escala.
Transações em Diferentes Sistemas
Nem todos os bancos de dados lidam com transações da mesma forma:
- MySQL (InnoDB) suporta transações ACID completas. O motor MyISAM mais antigo não suporta.
- PostgreSQL tem MVCC robusto e suporta isolamento
SERIALIZABLEcom verdadeiras garantias de serialização. - SQLite é totalmente compatível com ACID, mas serializa todas as escritas, tornando-o inadequado para cargas de trabalho de escrita com alta concorrência.
- MongoDB adicionou transações multi-documento na versão 4.0, mas elas têm mais overhead do que em bancos de dados relacionais tradicionais e devem ser usadas seletivamente.
Diretrizes Práticas para Usar Transações
- Mantenha as transações curtas. Transações de longa duração mantêm bloqueios ou retêm snapshots MVCC antigos, o que degrada o desempenho.
- Não envolva consultas somente leitura em transações desnecessariamente — especialmente em APIs de alto tráfego.
- Trate erros explicitamente. Sempre garanta que um
ROLLBACKaconteça em caso de falha, seja escrevendo SQL puro ou usando um ORM. - Escolha seu nível de isolamento deliberadamente.
READ COMMITTEDé um padrão razoável para a maioria das aplicações web. UseSERIALIZABLEapenas quando a correção exigir, e teste o impacto no desempenho.
Conclusão
As transações de banco de dados fornecem uma maneira confiável de manter os dados consistentes em múltiplas operações. Entender as propriedades ACID diz quais garantias você tem ao trabalhar. Conhecer seus níveis de isolamento e como seu banco de dados específico implementa MVCC diz o que essas garantias realmente custam — e onde estão os casos extremos. Esse conhecimento é o que separa desenvolvedores que usam transações de desenvolvedores que as usam bem.
Perguntas Frequentes
Use SERIALIZABLE quando sua aplicação exigir garantias estritas de correção, como cálculos financeiros ou gerenciamento de estoque onde transações concorrentes não devem produzir resultados conflitantes. Para a maioria das aplicações web, READ COMMITTED oferece um bom equilíbrio entre consistência e desempenho. Sempre faça benchmark de SERIALIZABLE no seu ambiente, pois ele pode reduzir a concorrência e levar a novas tentativas de transação, dependendo do motor do banco de dados.
A maioria dos bancos de dados automaticamente envolve cada instrução SQL individual em uma transação implícita, então um único INSERT ou UPDATE já é atômico. Transações explícitas se tornam necessárias quando você precisa agrupar múltiplas instruções em uma unidade de trabalho, garantindo que todas tenham sucesso ou todas falhem juntas. Envolver uma única instrução em BEGIN e COMMIT adiciona overhead sem benefício significativo.
Sempre use blocos try-catch ou equivalentes de tratamento de erros em torno da sua lógica de transação. Se qualquer operação dentro da transação lançar um erro, execute um ROLLBACK para desfazer todas as mudanças. Muitos ORMs e bibliotecas de banco de dados fornecem helpers de transação integrados que automaticamente revertem em caso de exceções. Evite suprimir erros silenciosamente, pois isso pode deixar seus dados em um estado inconsistente.
O bloqueio tradicional pode fazer com que leitores e escritores se bloqueiem mutuamente com mais frequência, o que limita a concorrência. O MVCC evita isso mantendo múltiplas versões de cada linha, para que os leitores acessem um snapshot consistente sem esperar pelos escritores. O trade-off é que versões antigas de linhas devem ser periodicamente limpas, como o PostgreSQL faz com seu processo VACUUM. O MVCC geralmente fornece melhor throughput para cargas de trabalho com muitas leituras.
Gain control over your UX
See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.