惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

C
Check Point Blog
罗磊的独立博客
量子位
Microsoft Azure Blog
Microsoft Azure Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
J
Java Code Geeks
M
MIT News - Artificial intelligence
月光博客
月光博客
IT之家
IT之家
D
DataBreaches.Net
A
About on SuperTechFans
博客园 - 三生石上(FineUI控件)
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Last Week in AI
Last Week in AI
D
Docker
The GitHub Blog
The GitHub Blog
B
Blog
V
Visual Studio Blog
博客园 - Franky
N
Netflix TechBlog - Medium
博客园 - 【当耐特】
Martin Fowler
Martin Fowler
博客园 - 聂微东
U
Unit 42

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant
O que é ACID?
Ewerton · 2026-05-09 · via DEV Community

Ewerton

O que é ACID?

alt text

Imagine um sistema de compra de ingressos, onde você precisa comprar um ingresso para um show. Você clica em "Comprar", o sistema verifica se tem ingressos disponíveis, reserva um para você, debita o valor do seu cartão de crédito e gera o ingresso. Agora imagine que, no meio desse processo, o sistema falha. O que acontece com o seu ingresso? E com o seu dinheiro?

Para garantir que isso não aconteça, os bancos de dados relacionais implementam o ACID, que é um conjunto de propriedades que garantem que as transações sejam processadas de forma confiável.

Atomicidade

Na Atomicidade uma transação ou é executada por completo ou não é executada. Não existe meio termo. No nosso exemplo, se o sistema falhar no meio do processo, o dinheiro não será debitado do cartão e o ingresso não será gerado. A transação será revertida por completo.

O exemplo clássico é uma transferência entre duas contas, onde o dinheiro sai de uma conta e entra na outra.

ActiveRecord::Base.transaction do
  david.withdrawal(100)
  maria.deposit(100)
end

Enter fullscreen mode Exit fullscreen mode

Esse exemplo só levará dinheiro de David e dará para Maria se nem withdrawal nem deposit levantarem uma exceção. As exceções forçarão um ROLLBACK que retorna o banco de dados ao estado anterior ao início da transação.

Mas, se nem withdrawal nem deposit levantarem uma exceção, então a transação será concluída com sucesso. Ou seja, o dinheiro sairá da conta de David e entrará na conta de Maria.

Consistência

A Consistência garante que a transação leve o banco de dados de um estado
válido para outro estado válido. Ou seja, se uma transação não for concluída com sucesso, o banco de dados não será alterado.

No exemplo dos ingressos, isso significa que não é possível comprar um ingresso com uma quantidade negativa ou com dados obrigatórios em branco. O banco rejeita qualquer operação que violaria suas regras.

ticket = Ticket.last
ticket.update(id:nil)
# =>
# PG::NotNullViolation: ERROR:  null value in column "id" of relation "tickets" 
# violates not-null constraint (ActiveRecord::NotNullViolation)
# DETAIL:  Failing row contains (null, 2026-04-29 06:01:26.693314, 173335, 
# 2026-05-06 19:20:28.89082, 90, 5).

Enter fullscreen mode Exit fullscreen mode

O banco recusa a operação e permanece exatamente como estava, nenhum estado inválido é persistido.

Isolamento

No Isolamento é garantido que transações não interfiram umas nas outras. Vamos voltar ao exemplo dos ingressos. Maria e João estão comprando o último ingresso disponível.
Se o isolamento não estiver ativo, João pode ver que há um ingresso disponível e iniciar a compra também. Nesse caso, ambos podem comprar o ingresso, o que não deveria acontecer. Para evitar isso, o isolamento garante que as transações não interfiram umas nas outras. A compra de Maria deve ser concluída antes que a de João possa ser iniciada.

# app/services/ticket_purchase_service.rb
class TicketPurchaseService
  class TicketUnavailableError < StandardError; end

  def self.purchase(ticket_id:, buyer_name:)
    ActiveRecord::Base.transaction(isolation: :serializable) do
      # WITH LOCK garante que apenas uma transação por vez acesse esse registro
      ticket = Ticket.lock("FOR UPDATE").find(ticket_id)

      raise TicketUnavailableError, "Ingresso não disponível!" unless ticket.available?

      # Simula o tempo de processamento (onde a corrida aconteceria sem isolamento)
      sleep(0.1)

      ticket.update!(available: false, owner_name: buyer_name)

      puts "[#{buyer_name}] ✅ Compra realizada com sucesso!"
      ticket
    end
  rescue TicketUnavailableError => e
    puts "[#{buyer_name}] ❌ #{e.message}"
    nil
  end
end

Enter fullscreen mode Exit fullscreen mode

Demonstração do problema SEM isolamento (race condition)

def demo_sem_isolamento(ticket_id)
  puts "\n=== SEM ISOLAMENTO ==="

  # Maria e João leem ao mesmo tempo que o ingresso está disponível
  thread_maria = Thread.new do
    ticket = Ticket.find(ticket_id)
    sleep(0.05) # simula processamento
    if ticket.available?
      ticket.update!(available: false, owner_name: "Maria")
      puts "[Maria] ✅ Compra realizada! (mas João também pode comprar)"
    end
  end

  thread_joao = Thread.new do
    ticket = Ticket.find(ticket_id)
    sleep(0.05) # lê o mesmo estado "disponível"
    if ticket.available?
      ticket.update!(available: false, owner_name: "João")
      puts "[João] ✅ Compra realizada! (ingresso duplicado 💥)"
    end
  end

  [thread_maria, thread_joao].each(&:join)
end

Enter fullscreen mode Exit fullscreen mode

Com isolamento via FOR UPDATE + transaction serializable

def demo_com_isolamento(ticket_id)
  puts "\n=== COM ISOLAMENTO ==="

  thread_maria = Thread.new do
    TicketPurchaseService.purchase(ticket_id: ticket_id, buyer_name: "Maria")
  end

  thread_joao = Thread.new do
    TicketPurchaseService.purchase(ticket_id: ticket_id, buyer_name: "João")
  end

  [thread_maria, thread_joao].each(&:join)
end

# Resultado esperado com isolamento:
# [Maria] ✅ Compra realizada com sucesso!
# [João]  ❌ Ingresso não disponível!

Enter fullscreen mode Exit fullscreen mode

Durabilidade

Na Durabilidade é garantido que uma vez que uma transação seja concluída com sucesso, ela não será desfeita, mesmo em caso de falha do sistema. No exemplo dos ingressos, uma vez que Maria compra o ingresso, ele não pode ser vendido novamente.

Isso significa que mesmo que o servidor reinicie logo após a compra, o registro da transação de Maria já está gravado permanentemente no banco.

ActiveRecord::Base.transaction do
  ticket.update!(available: false, owner_name: "Maria")
end

# Mesmo que o servidor caia aqui, a compra de Maria está salva.
ticket.reload
puts ticket.owner_name  # => "Maria"
puts ticket.available   # => false

Enter fullscreen mode Exit fullscreen mode

Conclusão

Voltando ao cenário inicial: você clica em "Comprar", o sistema processa tudo, mas no meio do caminho algo falha. Graças ao ACID, você não perde dinheiro sem
receber o ingresso (Atomicidade), o banco não aceita dadosinválidos no processo (Consistência), Maria e João não compram o mesmo ingresso ao mesmo tempo (Isolamento), e uma vez confirmada a compra, ela não some (Durabilidade). As quatro propriedades juntas são o que torna um banco de dados confiável para
transações do mundo real.