Processamento de Transações
Processamento de Transações
🌍 Analogia do Mundo Real
Imagine uma transferência bancária — você transfere 1000 da Conta A para a Conta B:
- Deduzir 1000 da Conta A
- Adicionar 1000 à Conta B
Se a etapa 1 tiver sucesso mas a etapa 2 falhar (ex: crash do sistema), A tem menos dinheiro mas B não recebeu — isso é um grande problema.
Uma transação vincula essas duas etapas em uma "operação atômica": ou ambas as etapas têm sucesso (COMMIT) ou ambas são revertidas (ROLLBACK). Nunca existe um estado "pela metade".
🎯 Conceitos Fundamentais
O que é uma Transação
Uma transação é uma sequência indivisível de operações SQL que ou todas executam com sucesso ou todas revertem. É o mecanismo central para garantir a consistência dos dados no banco de dados.
Propriedades ACID
| Propriedade | Inglês | Significado |
|---|---|---|
| Atomicidade | Atomicity | Todas as operações em uma transação ou têm sucesso ou são revertidas |
| Consistência | Consistency | O banco de dados transição de um estado consistente para outro |
| Isolamento | Isolation | Transações concorrentes não interferem umas nas outras, como se fossem executadas em série |
| Durabilidade | Durability | Uma vez confirmados, os dados são salvos permanentemente, mesmo se o sistema falhar |
BEGIN / COMMIT / ROLLBACK
-- Iniciar uma transação
BEGIN; -- ou START TRANSACTION
-- Executar uma série de operações
UPDATE accounts SET balance = balance - 1000 WHERE id = 1;
UPDATE accounts SET balance = balance + 1000 WHERE id = 2;
-- Tudo certo, confirmar
COMMIT;
-- Algo deu errado, reverter
ROLLBACK;
SAVEPOINT — Pontos de Salvamento
Defina um "ponto de verificação" dentro de uma transação. Você pode reverter para um ponto de salvamento específico sem afetar as operações anteriores a ele.
BEGIN;
INSERT INTO orders VALUES (1020, 101, 1, '2026-06-28', 500.00, 'pending');
SAVEPOINT sp1;
INSERT INTO order_items VALUES (1020, 1, 2, 100.00);
SAVEPOINT sp2;
-- Se a segunda etapa tiver um erro, revertemos apenas para sp1
ROLLBACK TO sp1;
-- Manter as operações da primeira etapa
COMMIT;
| Comando | Finalidade |
|---|---|
SAVEPOINT nome |
Definir um ponto de salvamento |
ROLLBACK TO nome |
Reverter para o ponto de salvamento especificado (mantém operações anteriores ao ponto) |
RELEASE SAVEPOINT nome |
Excluir um ponto de salvamento |
Níveis de Isolamento de Transações
Quando múltiplas transações operam nos mesmos dados simultaneamente, os seguintes problemas podem ocorrer:
| Problema | Descrição | Exemplo |
|---|---|---|
| Leitura Suja | Ler dados que outra transação não confirmou | Transação A modifica dados mas não confirmou; Transação B lê o valor modificado |
| Leitura Não Repetível | Ler a mesma linha duas vezes na mesma transação produz resultados diferentes | Transação A lê a mesma linha duas vez; entre as leituras, Transação B modifica e confirma essa linha |
| Leitura Fantasma | Executar a mesma consulta duas vezes na mesma transação produz contagens de linhas diferentes | Transação A consulta duas vezes; entre as consultas, Transação B insere novas linhas |
SQL define quatro níveis de isolamento:
| Nível de Isolamento | Leitura Suja | Leitura Não Repetível | Leitura Fantasma | Descrição |
|---|---|---|---|---|
| READ UNCOMMITTED | ✅ Possível | ✅ Possível | ✅ Possível | Nível mais baixo, raramente usado |
| READ COMMITTED | ❌ Não | ✅ Possível | ✅ Possível | Padrão do Oracle/PostgreSQL |
| REPEATABLE READ | ❌ Não | ❌ Não | ✅ Possível | Padrão do MySQL |
| SERIALIZABLE | ❌ Não | ❌ Não | ❌ Não | Nível mais alto, pior performance |
-- Ver nível de isolamento atual
SELECT @@transaction_isolation;
-- Definir nível de isolamento
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
Deadlocks
Um deadlock ocorre quando duas transações estão esperando que a outra libere recursos:
Transação A: Bloqueia Tabela 1 → Espera pela Tabela 2
Transação B: Bloqueia Tabela 2 → Espera pela Tabela 1
→ Esperando para sempre, nunca pode completar
Como o banco de dados lida com isso: Detecta automaticamente o deadlock, seleciona uma transação como "vítima" e a reverte, permitindo que a outra continue.
Estratégias para evitar deadlocks:
- Acessar tabelas e linhas em uma ordem fixa
- Reduzir o tempo que transações mantêm bloqueios
- Usar níveis de isolamento mais baixos
- Criar índices para consultas comuns para reduzir o escopo de bloqueio
Melhores Práticas
| Princípio | Descrição |
|---|---|
| Manter transações curtas | Reduzir tempo de retenção de bloqueios, melhorar concorrência |
| Não esperar entrada do usuário em uma transação | Transações devem completar rapidamente |
| Usar níveis de isolamento apropriados | Não usar o nível mais alto por padrão |
| Usar ordem de acesso consistente | Reduzir probabilidade de deadlock |
| Adicionar tratamento de erros | Reverter prontamente quando erros ocorrerem |
📝 Sintaxe Básica
-- Iniciar uma transação
BEGIN; -- MySQL, PostgreSQL
START TRANSACTION; -- Também suportado pelo MySQL
-- Confirmar a transação (todas as operações têm efeito permanente)
COMMIT;
-- Reverter a transação (desfaz todas as operações)
ROLLBACK;
-- Pontos de salvamento
SAVEPOINT nome_do_ponto;
ROLLBACK TO nome_do_ponto;
RELEASE SAVEPOINT nome_do_ponto;
-- Definir nível de isolamento
SET TRANSACTION ISOLATION LEVEL nível_de_isolamento;
-- Níveis de isolamento: READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE
-- Definir nível de isolamento global (afeta todas as novas conexões)
SET GLOBAL TRANSACTION ISOLATION LEVEL nível_de_isolamento;
-- Interruptor de autocommit (MySQL tem como padrão ON)
SET autocommit = 0; -- Desabilitar autocommit, requer COMMIT manual
SET autocommit = 1; -- Habilitar autocommit (padrão)
- MySQL tem como padrão
autocommit = 1, onde cada instrução SQL é confirmada automaticamente. Antes de usar transações, executeBEGINouSET autocommit = 0 - Instruções DDL (CREATE, ALTER, DROP) confirmam implicitamente a transação atual
- Quando uma conexão é desconectada, transações não confirmadas são automaticamente revertidas
📌 Exemplos
Exemplo: Transação de Criação de Pedido (Pedido + Dedução de Estoque) (Dificuldade ⭐⭐)
-- Cenário: Um cliente faz um pedido de um produto; é necessário criar o pedido e deduzir o estoque simultaneamente
BEGIN;
-- Etapa 1: Criar o pedido
INSERT INTO orders (order_id, customer_id, employee_id, order_date, total_amount, status)
VALUES (1020, 101, 1, '2026-06-28', 6999.00, 'pending');
-- Etapa 2: Deduzir estoque
UPDATE products SET stock = stock - 1 WHERE product_id = 1;
-- Etapa 3: Verificar se o estoque é suficiente (reverter se estoque < 0)
-- Na prática, isso geralmente é tratado pela lógica da aplicação ou triggers
-- Tudo certo, confirmar
COMMIT;
Se ocorrer um erro no meio:
BEGIN;
INSERT INTO orders (order_id, customer_id, employee_id, order_date, total_amount, status)
VALUES (1021, 102, 3, '2026-06-28', 129.00, 'pending');
UPDATE products SET stock = stock - 1 WHERE product_id = 2;
-- Suponha que descobrimos estoque insuficiente, reverter toda a transação
ROLLBACK;
-- Tanto o pedido quanto o estoque são restaurados ao estado anterior à transação
Exemplo: Usando SAVEPOINT para Reversão Parcial (Dificuldade ⭐⭐⭐)
BEGIN;
-- Primeiro pedido: bem-sucedido
INSERT INTO orders VALUES (1022, 103, 4, '2026-06-28', 3500.00, 'pending');
UPDATE products SET stock = stock - 1 WHERE product_id = 4;
SAVEPOINT after_first_order;
-- Segundo pedido: erro
INSERT INTO orders VALUES (1023, 104, 4, '2026-06-28', 2200.00, 'pending');
UPDATE products SET stock = stock - 1 WHERE product_id = 5;
SAVEPOINT after_second_order;
-- Descobrimos um problema com o segundo pedido, reverter para após o primeiro
ROLLBACK TO after_first_order;
-- O primeiro pedido ainda é válido, confirmar
COMMIT;
-- Resultado: Pedido 1022 é mantido, Pedido 1023 é revertido
Verificação:
SELECT order_id, total_amount, status FROM orders WHERE order_id >= 1022;
order_id | total_amount | status
---------+-------------+--------
1022 | 3500.00 | pending
Explicação: ROLLBACK TO after_first_order apenas desfaz operações após o ponto de salvamento. O primeiro pedido e a dedução de estoque são preservados.
🎬 Prática de Cenários
Cenário 1: Ajuste Salarial em Lote de Funcionários (com Tratamento de Erros) (Dificuldade ⭐⭐⭐)
BEGIN;
-- Dar aumento de 10% para o departamento de Vendas
UPDATE employees
SET salary = salary * 1.10
WHERE department_id = (SELECT department_id FROM departments WHERE department_name = 'Sales');
SAVEPOINT after_sales_raise;
-- Dar aumento de 8% para o departamento de Tecnologia
UPDATE employees
SET salary = salary * 1.08
WHERE department_id = (SELECT department_id FROM departments WHERE department_name = 'Tech');
SAVEPOINT after_tech_raise;
-- Suponha que a aprovação do orçamento não passou, desfazer apenas o aumento do departamento de Tecnologia
ROLLBACK TO after_sales_raise;
-- O aumento do departamento de Vendas é mantido, confirmar
COMMIT;
Ponto-chave: SAVEPOINT permite "reversão parcial", adequado para operações em lote que requerem controle flexível.
Cenário 2: Simulando uma Transferência e Tratando Deadlocks (Dificuldade ⭐⭐⭐)
-- Sessão A: Transferir orçamento do departamento 1 para o departamento 2
BEGIN;
UPDATE departments SET budget = budget - 50000 WHERE department_id = 1;
-- Aguardar um momento...
UPDATE departments SET budget = budget + 50000 WHERE department_id = 2;
COMMIT;
-- Sessão B: Simultaneamente transferir orçamento do departamento 2 para o departamento 1 (outra conexão)
BEGIN;
UPDATE departments SET budget = budget - 30000 WHERE department_id = 2;
UPDATE departments SET budget = budget + 30000 WHERE department_id = 1;
COMMIT;
Prevenção de deadlock:
-- Ambas as sessões acessam departamentos em ordem ascendente por department_id
-- Sessão A:
BEGIN;
UPDATE departments SET budget = budget - 50000 WHERE department_id = 1; -- Bloqueia 1 primeiro
UPDATE departments SET budget = budget + 50000 WHERE department_id = 2; -- Depois bloqueia 2
COMMIT;
-- Sessão B:
BEGIN;
UPDATE departments SET budget = budget + 30000 WHERE department_id = 1; -- Também bloqueia 1 primeiro
UPDATE departments SET budget = budget - 30000 WHERE department_id = 2; -- Depois bloqueia 2
COMMIT;
Ponto-chave: Usar uma ordem de acesso consistente é a maneira mais simples e eficaz de evitar deadlocks.
❓ Perguntas Frequentes
P: MySQL tem autocommit como padrão — como uso transações? R: MySQL tem como padrão
autocommit = 1, onde cada instrução SQL é confirmada automaticamente. Para usar transações, executeBEGIN(ouSTART TRANSACTION) primeiro; as instruções SQL seguintes não serão confirmadas automaticamente até que você executeCOMMITouROLLBACK.
P: Posso fazer ROLLBACK após COMMIT? R: Não.
COMMITé o fim de uma transação; uma vez confirmados, os dados são salvos permanentemente e não podem ser desfeitos. Para "desfazer" dados confirmados, você deve executar uma operação reversa em uma nova transação (ex: UPDATE de volta ao valor original).
P: Qual nível de isolamento devo escolher? R: Para a maioria dos cenários, use o padrão do banco de dados (MySQL tem como padrão
REPEATABLE READ, Oracle/PostgreSQL tem como padrãoREAD COMMITTED). UseSERIALIZABLEapenas quando precisar explicitamente prevenir leituras fantasmas e puder aceitar o compromisso de performance.
P: Instruções DDL (CREATE TABLE, ALTER TABLE) são controladas por transações? R: Não. Instruções DDL confirmam implicitamente a transação atual. Após executar DDL em uma transação, as instruções SQL anteriores não podem mais ser revertidas. Este é o comportamento do MySQL; no PostgreSQL, DDL pode ser revertida.
📖 Resumo
| Conceito | Descrição |
|---|---|
| Transação | Um grupo de operações de banco de dados indivisíveis |
| ACID | Atomicidade, Consistência, Isolamento, Durabilidade |
| BEGIN | Iniciar uma transação |
| COMMIT | Confirmar uma transação, torná-la permanente |
| ROLLBACK | Reverter uma transação, desfazer tudo |
| SAVEPOINT | Um ponto de verificação dentro de uma transação, suporta reversão parcial |
| Nível de Isolamento | Controla a visibilidade entre transações concorrentes |
| Deadlock | Duas transações esperando uma pela outra; o banco de dados detecta automaticamente e reverte uma |
- Manter transações curtas para reduzir o tempo de retenção de bloqueios
- Acessar recursos em uma ordem fixa para reduzir deadlocks
- Escolher o nível de isolamento apropriado com base nas necessidades do negócio
📝 Exercícios
- Escreva uma transação que insere um novo pedido na tabela
ordersenquanto deduz o estoque do produto correspondente na tabelaproducts. Se o estoque for insuficiente, reverter toda a transação. - Use
SAVEPOINTpara implementar uma transação que insere 3 registros de pedidos, depois reverte o 3º enquanto mantém os 2 primeiros. - Verifique o nível de isolamento padrão do seu banco de dados e tente definir para
READ COMMITTEDpara observar o impacto em leituras e escritas concorrentes. - Questão reflexiva: Se uma transação levar muito tempo para executar, qual será o impacto em outras transações? Como isso pode ser otimizado?
Próxima Lição
👉 22-stored-procedures - Procedimentos Armazenados: Aprenda sobre criação e chamada de procedimentos armazenados, parâmetros de entrada/saída, instruções de controle de fluxo e as aplicações práticas de procedimentos armazenados.



