Específicos · Engenharia de Software
Transações distribuídas: ACID, 2PC × Saga, idempotência, outbox
Tudo ou nada é fácil num banco só; entre serviços, ou se bloqueia para coordenar (2PC) ou se aceita consistência eventual com compensação (Saga) — e aí idempotência e outbox passam a ser obrigatórios.
Altíssima5 itens no tópico
A ideia que organiza o assunto
Uma transação é uma promessa: ou tudo acontece, ou nada acontece, e enquanto acontece ninguém vê o meio do caminho. Num único banco de dados essa promessa é barata — há um log, um gerenciador de bloqueios e um ponto só de decisão.
O assunto todo nasce de perguntar o que sobra dessa promessa quando o trabalho se espalha por dois ou mais recursos independentes: dois bancos, um banco e uma fila, três microsserviços. Agora há rede no meio, e rede falha justamente no instante entre “já gravei aqui” e “vou avisar lá”. Não existe mais um ponto único que decida, e qualquer coordenação precisa sobreviver à queda do coordenador.
Por isso, a pergunta que organiza o tópico é: quem decide o desfecho, e o que se perde enquanto ele não decide? Há duas respostas, e elas se excluem. Ou se mantém a atomicidade real, com um coordenador que faz todos prometerem antes de qualquer um efetivar — é o 2PC, e o preço é bloqueio e indisponibilidade enquanto o coordenador estiver mudo. Ou se abre mão da atomicidade global e se divide o trabalho em etapas locais que efetivam de imediato, cada uma com uma compensação que desfaz seu efeito se a etapa seguinte falhar — é a Saga, e o preço é que estados intermediários ficam visíveis.
Duas consequências práticas seguem da segunda escolha e caem junto com ela. Se mensagens podem ser reentregues, cada operação precisa ser idempotente — executar duas vezes tem de valer por uma. E se é preciso gravar no banco e publicar um evento, os dois atos não cabem numa transação comum: grava-se o evento numa tabela do mesmo banco, na mesma transação, e um processo separado o publica depois. É o outbox.
Como funciona
ACID, propriedade a propriedade. Atomicidade: a transação é unidade indivisível, ou seja, efetiva-se por inteiro ou não deixa efeito nenhum — e por isso nenhuma outra transação chega a conviver com metade do trabalho. Consistência: a transação leva o banco de um estado válido a outro estado válido, preservando as regras de integridade declaradas. Isolamento: transações concorrentes não interferem umas nas outras, e o resultado final é o mesmo que se obteria executando-as em sequência — é a definição de serialização. Durabilidade: efetivada a transação, o efeito sobrevive a falha, porque foi registrado em meio persistente antes da confirmação.
O isolamento tem graus, e é o único dos quatro que se negocia por desempenho. Os níveis padronizados vão de leitura não confirmada a serializável, e cada degrau admite uma anomalia a mais: leitura suja, leitura não repetível e leitura fantasma. Muitos bancos implementam o isolamento sem bloquear leitores por meio de MVCC, o controle de concorrência multiversão: cada transação enxerga a versão do dado válida no instante em que começou, e escritas criam versões novas em vez de sobrescrever. É o caso do InnoDB no MySQL, que suporta transações ACID, bloqueio em nível de linha e MVCC, e organiza os dados num índice agrupado pela chave primária.
2PC, o protocolo de efetivação em duas fases. Um coordenador conduz. Na fase de preparação, ele pergunta a cada participante se pode efetivar; cada um faz o trabalho, registra em log durável e responde “pronto”, ficando desde então bloqueado — não pode nem confirmar nem desfazer sozinho. Na fase de efetivação, se todos responderam que sim, o coordenador manda confirmar; se um só respondeu que não, manda desfazer. Isso entrega atomicidade real entre recursos, e é o que está por trás do XA e do commit distribuído. O defeito é estrutural: enquanto o coordenador não decide, os participantes seguram recursos, e se ele cai depois da preparação, a transação fica em dúvida até alguém resolver manualmente. É por isso que 2PC não escala e não combina com microsserviços autônomos.
Saga. A transação longa vira uma sequência de transações locais, cada uma efetivada no seu próprio serviço. Se a etapa n falha, executam-se as compensações das etapas de 1 a n-1, em ordem inversa — não é um desfazer de banco, é uma operação de negócio que anula a anterior: estorno, cancelamento, liberação de reserva. A saga pode ser coreografada, com os serviços reagindo a eventos uns dos outros, ou orquestrada, com um componente central conduzindo os passos. Não há isolamento entre as etapas: o mundo vê o pedido criado antes de o pagamento confirmar, e isso é uma decisão de negócio, não um acidente.
Idempotência e outbox. Em sistemas de mensagem, a entrega garantida é normalmente “ao menos uma vez”, o que significa repetição. A defesa é a idempotência: cada requisição carrega uma chave, o receptor registra as chaves já processadas e descarta a repetição, de modo que o efeito de n execuções seja o de uma. O outbox resolve o outro lado: como não existe transação que abranja o banco e o intermediário de mensagens, a aplicação grava o evento numa tabela de saída dentro da mesma transação que altera o dado, e um processo assíncrono lê essa tabela e publica. Se ele falhar, republica — daí a idempotência ser exigida do consumidor.
O que decide os itens
As quatro propriedades, e o que cada uma responde:
| garante | a pergunta que ela responde | |
|---|---|---|
| Atomicidade | tudo ou nada; sem efeito parcial | e se falhar no meio? |
| Consistência | estado válido antes e depois, pelas regras do banco | as restrições continuam valendo? |
| Isolamento | concorrentes não interferem; resultado equivale ao sequencial | e se duas rodarem juntas? |
| Durabilidade | efeito sobrevive a falha após a confirmação | e se a energia cair depois do commit? |
Atomicidade e isolamento se tocam: por ser indivisível, a transação não expõe metade do seu trabalho às demais. A diferença de ênfase é que a atomicidade fala do desfecho da transação e o isolamento fala da concorrência entre elas.
2PC × Saga:
| 2PC | Saga | |
|---|---|---|
| atomicidade global | sim, real | não: cada etapa efetiva sozinha |
| isolamento entre etapas | sim, com bloqueio | não: estados intermediários são visíveis |
| como desfaz | rollback coordenado | compensação de negócio, em ordem inversa |
| ponto fraco | coordenador é ponto único; transação em dúvida | complexidade de compensar e de raciocinar |
| serve a | recursos transacionais no mesmo domínio de confiança | microsserviços autônomos e longa duração |
Fronteiras que a banca repete: ACID é propriedade de transação, não de armazenamento, de infraestrutura nem de nuvem; consistência no ACID é integridade declarada, e não o “C” do teorema CAP, que trata de réplicas; durabilidade fala do que acontece depois da confirmação; 2PC bloqueia e por isso custa disponibilidade; Saga não tem isolamento; e entrega de mensagem “ao menos uma vez” exige consumidor idempotente.
Números que caem
| ACID | 4 propriedades |
| 2PC | 2 fases: preparação e efetivação |
| 3PC | 3 fases: acrescenta a pré-efetivação para reduzir bloqueio |
| níveis de isolamento do padrão SQL | 4: leitura não confirmada, leitura confirmada, leitura repetível, serializável |
| anomalias de concorrência | 3: leitura suja, leitura não repetível, leitura fantasma |
| teorema CAP | 3 garantias, das quais se escolhem 2 sob partição |
Como a CEBRASPE derruba você aqui
A medição está fechada, e o que ela mostra primeiro é que o título não descreve a amostra. Os cinco itens do tópico estão explicados: quatro Certos e um Errado, e todos os cinco giram em torno do ACID — nenhum cobra 2PC, Saga, idempotência ou outbox, que é o que dá nome ao tópico. Tudo o que as seções anteriores dizem sobre 2PC e Saga é, portanto, conteúdo de edital ainda não cobrado nesta amostra: está aqui porque decide item em qualquer caderno de microsserviços e porque é o que o nome do tópico promete, não porque estes cinco itens o tenham exigido.
Com um único item errado não existe padrão a declarar. Existe um item, e o que ele faz está descrito abaixo; o resto vem rotulado como não medido.
Esticar o ACID para além da transação — o único item errado da amostra. O item define ACID corretamente — integridade e segurança dos dados — e acrescenta uma atribuição que não é dele: ser “responsável pelo armazenamento em plataformas de cloud computing”. ACID descreve o comportamento de uma transação; onde os bytes ficam guardados é outro problema, resolvido por sistema de arquivos, replicação e serviço de armazenamento. Defesa: leia até o fim e confira se a última oração ainda fala de transação.
Colar o ACID em temas vizinhos. É o formato de 4 dos 5 itens, e os quatro são Certo: o ACID chega como aposto dentro de um enunciado de Big Data, de arquitetura de dados ou de SGBD específico — ligado a um dos Vs, ao InnoDB do MySQL, a um modelo de arquitetura. Note o que isso significa para a prova: neste tópico a soma de duas afirmações verdadeiras, sem exclusividade nem dependência entre elas, veio certa nas duas vezes em que apareceu — um dos Vs do Big Data mais a atomicidade do ACID, nos dois cadernos. Julgue as duas partes separadamente: primeiro a afirmação sobre o tema principal, depois a afirmação sobre a propriedade transacional.
Trocar uma propriedade pela outra — conhecida do assunto, não medida aqui. Nenhum dos cinco itens troca uma letra do ACID pela outra: os três que nomeiam uma propriedade — atomicidade duas vezes, isolamento uma — descrevem cada uma corretamente e são Certo. Com quatro nomes curtos e definições próximas a troca segue barata: durabilidade descrita como atomicidade, consistência descrita como isolamento. Antes de julgar, responda mentalmente a pergunta de cada uma: e se falhar no meio, e se duas rodarem juntas, e se a energia cair depois do commit.
Confundir o C do ACID com o C do CAP — também não medida aqui. Não apareceu em nenhum dos cinco itens, mas são coisas diferentes e a coincidência de letra é um convite. No ACID, consistência é respeitar as regras de integridade do esquema; no CAP, é todas as réplicas responderem o mesmo valor. Item que use uma definição sob o rótulo da outra está trocando de teoria no meio da frase.
Erros clássicos
Achar que atomicidade é sobre concorrência e isolamento é sobre falha. É o contrário: atomicidade responde ao que acontece se a transação não termina; isolamento responde ao que uma transação enxerga da outra enquanto ambas rodam.
Tratar ACID como característica de banco de dados inteiro. ACID qualifica a execução de transações. Um mesmo produto pode ter motores com garantias diferentes — no MySQL, o InnoDB oferece transações ACID, bloqueio em nível de linha e MVCC.
Supor que 2PC é a solução natural para microsserviços. O bloqueio durante a fase de preparação amarra serviços que deveriam ser autônomos e transfere a disponibilidade de todos para o coordenador. Em arquitetura distribuída moderna, a resposta esperada é Saga com compensação.
Esperar isolamento numa Saga. Não há: cada etapa efetiva de imediato e o estado intermediário é visível. Quem precisa de invisibilidade do meio do caminho precisa de transação local, não de saga.
Confundir compensação com rollback. Rollback apaga o efeito porque ele ainda não foi tornado permanente; compensação é uma nova transação de negócio, que anula o efeito de uma anterior já efetivada — e que pode, ela própria, falhar.
Achar que basta entregar a mensagem uma vez. Praticamente todo intermediário entrega ao menos uma vez, e reentrega em caso de dúvida. Sem chave de idempotência no consumidor, a repetição vira cobrança dobrada.
LidoPraticado