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

Reels - Sistemas e Arquitetura

@bytebytego

ByteByteGo no Facebook

Referências e Leituras Recomendadas

@mjovanovictech

Como testar que sua API é resiliente e segura para produção real

Ver post completo no X →
@mjovanovictech

Implementando padrões de resiliência em .NET Core com exemplos reais

Ver post completo no X →
@mjovanovictech

Vertical Slice Architecture - organizando sistemas para escala

Ver post completo no X →
@mjovanovictech

5 anos com Clean Architecture - lições de sistemas em produção

Ver post completo no X →
@mjovanovictech

Design de APIs resilientes - retry, backoff e idempotência juntos

Ver post completo no X →
@mjovanovictech

Monolito vs Microsserviços - como escolher para cada contexto

Ver post completo no X →

Links Úteis