O que são operações atômicas
A garantia de que uma operação não pode ser parcialmente executada
Uma operação atômica é aquela que ou executa por completo ou não executa nada - nunca termina em um estado intermediário visível para outros. O nome vem da física: átomo era considerado indivisível. Em sistemas de informação, uma operação atômica é indivisível do ponto de vista externo: nenhum outro processo pode observar o sistema em um estado parcial durante sua execução. Essa garantia é fundamental para operações financeiras, estoque, reservas e qualquer cenário onde um conjunto de mudanças precisa acontecer como uma unidade coerente. Sem atomicidade, falhas parciais deixam o sistema em estado inconsistente que pode ser impossível de corrigir automaticamente.
O problema da não-atomicidade em transferências bancárias
O exemplo clássico que explica por que atomicidade é crítica
Considere uma transferência de R$100 entre duas contas: debitar da conta A e creditar na conta B. Se o sistema fizer os dois passos separadamente sem atomicidade, podem acontecer dois desastres: falha após debitar A mas antes de creditar B (R$100 some do sistema - cliente perde dinheiro), ou falha antes de debitar A mas após creditar B (R$100 aparece do nada - banco perde dinheiro). A solução são transações de banco de dados: BEGIN TRANSACTION, executar o débito e o crédito, e só então COMMIT. Se qualquer passo falhar, o ROLLBACK desfaz tudo, voltando ao estado anterior como se nada tivesse acontecido.
Propriedades ACID - a base das transações relacionais
Atomicidade, Consistência, Isolamento e Durabilidade
As propriedades ACID definem o comportamento das transações em bancos relacionais. Atomicidade: tudo ou nada. Consistência: a transação leva o banco de um estado válido para outro estado válido, respeitando constraints e regras de negócio. Isolamento: transações concorrentes não interferem entre si - uma transação em andamento não vê mudanças de outras transações não confirmadas. Durabilidade: uma vez confirmada (COMMIT), a transação persiste mesmo em falhas de hardware, pois foi escrita em log persistente (WAL). Bancos como PostgreSQL, MySQL e SQL Server implementam ACID completo. Bancos NoSQL frequentemente sacrificam isolamento por performance, exigindo que o desenvolvedor gerencie atomicidade de forma explícita.
Atomicidade em banco NoSQL - o desafio do MongoDB e similares
Documentos únicos são atômicos; múltiplos documentos exigem transações explícitas
No MongoDB, operações em um único documento são atômicas por design: todas as modificações em um updateOne acontecem atomicamente sem possibilidade de estado parcial. Isso é poderoso: modelar dados relacionados dentro do mesmo documento (embedded) elimina a necessidade de transações multi-documento para muitos casos de uso. Para operações que precisam modificar múltiplos documentos atomicamente, o MongoDB 4.0 introduziu transações multi-documento com semântica ACID - mas com custo de performance e complexidade significativos. A regra prática é: prefira modelar dados que precisam de atomicidade dentro do mesmo documento; use transações multi-documento apenas quando inevitável.
Operações atômicas no Redis
MULTI/EXEC, scripts Lua e comandos atômicos nativos
O Redis oferece múltiplas formas de atomicidade. Comandos individuais como INCR, SETNX, LPUSH são atômicos por natureza - executam como uma operação indivisível no thread único do Redis. Para sequências de comandos atômicas, o Redis suporta MULTI/EXEC (transações otimistas que executam como bloco atômico) e scripts Lua (executados atomicamente no servidor, sem interrupção). GETSET e variantes como GETDEL combinam operações de leitura e escrita em uma única chamada atômica. O clássico padrão de lock distribuído - SET key value NX PX milliseconds - é atômico e é a base do Redlock, o algoritmo de distributed lock do Redis.
Race conditions sem atomicidade
Dois processos modificando o mesmo dado ao mesmo tempo
Race condition é o que acontece quando atomicidade está ausente e dois processos operam sobre o mesmo dado simultaneamente. Exemplo: dois workers verificam se o estoque de um produto é maior que zero (ambos veem 1), ambos decrementam (resultado: -1, estoque negativo). A solução é tornar a verificação e a modificação uma operação atômica: UPDATE products SET stock = stock - 1 WHERE id = $1 AND stock > 0 - o banco garante que apenas um dos updates será bem-sucedido quando executados concorrentemente. Em Redis: WATCH key + MULTI/EXEC com verificação otimista. Em filas: SELECT FOR UPDATE com lock pessimista.
Locks e mutexes - serializar acesso a recursos compartilhados
Garantir que apenas um processo por vez acesse um recurso crítico
Quando atomicidade nativa não é possível (como em operações que envolvem múltiplos sistemas), locks garantem exclusão mútua: apenas um processo por vez executa a seção crítica. Locks otimistas (optimistic locking) usam versioning - o registro tem um campo de versão incrementado em cada update; se a versão mudou desde a leitura, o update falha e a operação deve ser refeita. Locks pessimistas (SELECT FOR UPDATE) bloqueiam o registro para outros processos enquanto a transação está aberta - mais seguro mas pode causar deadlocks e degradação de performance em alto volume. A escolha depende da taxa de conflito esperada: optimistic para conflitos raros, pessimistic para conflitos frequentes.
Duas fases de commit - atomicidade entre sistemas distintos
Como coordenar uma operação atômica que envolve múltiplos bancos ou serviços
Dois-fases de commit (2PC) é o protocolo para operações atômicas que envolvem múltiplos sistemas independentes - como uma operação que modifica banco SQL e envia mensagem para fila, ou que atualiza dois microserviços diferentes. O protocolo tem uma fase de preparação (coordinator pergunta a todos os participantes se estão prontos para commitar) e uma fase de commit (todos confirmam ou todos fazem rollback). O problema do 2PC é que ele é bloqueante: se o coordinator cair durante a fase de commit, os participantes ficam bloqueados esperando decisão. Alternativas modernas como Saga pattern resolvem isso com compensating transactions - desfazer individualmente o que já foi feito.
Saga pattern - atomicidade distribuída sem 2PC
Sequência de transações locais com compensação em caso de falha
O Saga pattern divide uma operação distribuída em uma sequência de transações locais, cada uma com uma transação compensatória que desfaz o efeito. Se a operação "criar pedido + debitar pagamento + reservar estoque" falhar no passo de estoque, o Saga executa as compensações: estornar o pagamento e cancelar o pedido. O resultado não é atomicidade perfeita (o sistema passa por estados intermediários visíveis), mas é eventual consistency com garantia de que o sistema sempre termina em um estado consistente. É o padrão mais usado em microsserviços para operações que cruzam fronteiras de serviços, onde 2PC seria impraticável.
Conclusão - atomicidade é a base da integridade de dados
Sem atomicidade, qualquer falha pode deixar dados irrecuperáveis
Atomicidade não é um detalhe de implementação - é o fundamento que garante que o sistema pode ser confiado com dados financeiros, médicos, logísticos ou qualquer outro dado onde estado parcial é inaceitável. Use transações ACID em bancos relacionais para operações críticas. Modele documentos MongoDB para evitar a necessidade de transações multi-documento. Use operações Redis nativas (INCR, SETNX, scripts Lua) para atomicidade em memória. Para sistemas distribuídos, implemente Saga com compensating transactions em vez de depender de 2PC frágil. Continue em: Fundamentos obrigatórios antes de produção.
Operações Atômicas e Transações - Vídeos
Idempotency in Cows and REST APIs - base conceitual para atomicidade
Idempotency Explained - REST API e operações atômicas
Idempotency in APIs Explained - como evitar estados parciais
What is API Idempotency and Why Is It Important? - Be A Better Dev
Algorithms You Should Know For System Design - ByteByteGo
The Best System Design Series - ByteByteGo
Reels - Sistemas e Arquitetura
@bytebytego
ByteByteGo no Facebook
Referências e Leituras Recomendadas
Como testar que sua API é resiliente e segura para produção real
Ver post completo no X →Implementando padrões de resiliência em .NET Core com exemplos reais
Ver post completo no X →Vertical Slice Architecture - organizando sistemas para escala
Ver post completo no X →5 anos com Clean Architecture - lições de sistemas em produção
Ver post completo no X →Design de APIs resilientes - retry, backoff e idempotência juntos
Ver post completo no X →Monolito vs Microsserviços - como escolher para cada contexto
Ver post completo no X →