Como as fases de validação e atualização geralmente têm curta duração, uma simplificação pode ser obtida com uma nova regra:
Apenas uma transação pode estar na fase de validação e atualização em um dado momento.
Uso de seção crítica para restringir o acesso.
Neste caso, quando duas transações não podem se sobrepor na fase de atualização a Regra 3 é satisfeita.
Muito restritiva se toda a validação e atualização estiverem na seção crítica.
A validação de uma transação deve garantir que as regras 1 e 2 sejam obedecidas, testando as sobreposições entre os objetos de pares de transações e .
Estratégias de Validação
Na fase de validação, o sistema verifica conflitos de leitura-escrita e escrita-escrita para garantir que os conflitos sigam uma única direção temporal.
Há duas abordagens principais:
Validação para trás: compara a transação atual com transações já confirmadas desde o início de sua execução (foco na Regra 2).
Validação para frente: compara a transação que está tentando confirmar com transações mais novas ainda em execução (foco na Regra 1).
A validação para trás é a abordagem mais comum.
Validação para Trás
Como todas as operações de leitura das transações sobrepostas anteriores foram executadas antes que a validação de começasse, elas não podem ser afetadas pelas escritas da transação corrente (Regra 1 satisfeita).
A validação da transação verifica se seu conjunto de leitura se sobrepõe a qualquer um dos conjuntos de escrita das transações sobrepostas anteriores (Regra 2)
Se houver qualquer sobreposição, a validação falhará.
Validação para Trás (cont.)
Seja startTn o maior número de transação atribuído (para alguma outra transação efetivada) no momento em que a transação começou sua fase de trabalho.
Seja finishTn o maior número de transação atribuído no momento em que entrou na fase de validação.
boolean valid = true;
for (int Ti = startTn + 1; Ti <= finishTn; Ti ++){
if (conjunto de leitura de Tv possui interseção com o
conjunto de escrita de Ti)
valid = false;
}
Validação para Trás (cont.)
Validação para Frente
Na validação para frente da transação , o conjunto de escrita de é comparado com os conjuntos de leitura de todas as transações ativas sobrepostas, isto é, ainda na fase de trabalho (Regra 1).
A Regra 2 é automaticamente satisfeita, pois as transações ativas só escrevem depois que tiver terminado.
Seja active1 a activeN os identificadores (consecutivos) das transações ativas.
boolean valid = true;
for (int Tid = active1; Tid <= activeN; Tid ++){
if (conjunto de escrita de Tv possui interseção com o
conjunto de leitura de Tid)
valid = false;
}
Uma transação recebe um número apenas quando executa um closeTransaction.
Validação para Frente (cont.)
Validação para Frente (cont.)
Como os conjuntos de leitura da transação que está sendo validada não são incluídos na verificação, as transações somente de leitura são sempre validadas.
Como as transações que estão sendo comparadas com a transação que está sendo validada ainda estão ativas, há várias alternativas para tratar este conflito:
adiar a validação até um momento posterior quando as transações conflitantes tiverem terminado;
Não há garantias que o conflito desaparecerá.
cancelar todas as operações ativas conflitantes e efetivar a transação que está sendo validada;
cancelar a transação que estiver sendo validada.
Commit de Distribuído
Em uma transação distribuída, várias máquinas participam da mesma operação.
Exemplo:
Serviço de pagamento
Serviço de estoque
Serviço de entrega
Serviço de pedidos
Pergunta: Como garantir que todos confirmem ou todos cancelem?
Commit Distribuído
Uma transação distribuída só deve ser confirmada se todos os participantes puderem confirmar sua parte local. Caso contrário: A transação global deve ser abortada.
Exemplo: Compra em e-commerce.
Criar pedido
Confirmar pagamento
Reduzir estoque
Reservar entrega
Se o pagamento for aprovado, mas o estoque falhar, o sistema fica inconsistente.
Two-Phase Commit Protocol (2PC)
O 2PC divide a decisão em duas fases: Fase de votação e Fase de decisão.
Objetivo: Obter uma decisão global única: commit ou abort.
Coordenador:
Inicia o protocolo
Solicita votos
Decide o resultado global
Informa a decisão final
Participantes:
Executam subtransações locais
Votam commit ou abort
Seguem a decisão do coordenador
2PC: Fase 1 (Votação)
O coordenador envia uma mensagem para todos os participantes: vote request.
Cada participante verifica se consegue confirmar sua parte da transação.
Cada participante responde:
vote commit se está pronto para confirmar.
vote abort se não pode confirmar.
2PC: Fase 1 (Votação) - Quando votar commit?
Um participante vota commit quando:
Executou sua parte local com sucesso
Gravou informações necessárias no log
Está preparado para confirmar posteriormente
Consegue garantir recuperação após falha
2PC: Fase 1 (Votação) - Quando votar abort?
Um participante vota abort quando:
Ocorreu erro local
Não conseguiu executar sua operação
Não conseguiu registrar informações no log
Houve violação de regra de negócio
Exemplo:
estoque insuficiente
2PC: Fase 2 (Decisão)
O coordenador analisa os votos.
Se todos votarem commit:
global commit
Se algum votar abort ou não responder:
global abort
2PC: Fase 2 (Decisão) - Caso 1: Todos votam commit
Participante A → vote commit
Participante B → vote commit
Participante C → vote commit
Decisão do coordenador:
global commit
Resultado: Todos confirmam suas alterações locais.
2PC: Fase 2 (Decisão) - Caso 2: Algum participante vota abort
Participante A → vote commit
Participante B → vote abort
Participante C → vote commit
Decisão do coordenador:
global abort
Resultado: Todos desfazem suas alterações locais.
2PC: Fase 2 (Decisão) - Caso 3: Participante não responde
Se um participante não responder dentro do tempo esperado:
timeout
O coordenador pode decidir:
global abort
Motivo: Sem unanimidade, não há commit global seguro.
O pagamento vota commit, o estoque vota commit, mas a entrega não responde.
Perguntas:
Qual deve ser a decisão do coordenador?
Por que essa decisão é segura?
Qual propriedade ACID está sendo protegida?
Questão 2
Em um sistema de saúde, uma transação distribuída atualiza:
Estoque da Cardiologia
Estoque da Emergência
Registro de auditoria
Pergunta: O 2PC seria adequado? Quais riscos existiriam se o coordenador falhasse?
---
# Papel do log
O log é essencial para recuperação.
Antes de votar `commit`, o participante deve registrar que está preparado.
Exemplo:
```text
<ready T1>
```
Antes da decisão final, o coordenador registra:
```text
<global commit T1>
```
ou
```text
<global abort T1>
```
---
# Por que registrar no log?
Porque falhas podem ocorrer entre mensagens.
Exemplo:
```text
Participante vota commit
Participante falha antes de receber decisão final
```
Ao reiniciar, ele consulta o log para saber em qual estado estava.
# Quando usar 2PC?
Use 2PC quando:
* A transação é curta
* Os participantes são confiáveis
* Há controle sobre os sistemas envolvidos
* Consistência forte é obrigatória
* Todos os participantes suportam transações
---
# Quando evitar 2PC?
Evite 2PC quando:
* A transação é longa
* Os serviços são muito autônomos
* A rede é instável
* Alta disponibilidade é prioridade
* O custo de bloqueio é muito alto
---
# Exemplo de aplicação adequada
Transferência entre contas em bancos internos do mesmo sistema:
```text
Debitar conta A
Creditar conta B
Registrar operação
```
Nesse caso, atomicidade forte é essencial.
---
# Diagrama conceitual
```text
Fase 1: Votação
Coordenador ─────────────► Participantes
vote request
Participantes ───────────► Coordenador
vote commit / vote abort
Fase 2: Decisão
Coordenador ─────────────► Participantes
global commit / global abort
```
---
# Conteúdo Extra
---
# 2PC: Pseudocódigo do coordenador
```text
enviar vote request para todos
aguardar votos
se todos responderem vote commit:
escrever global commit no log
enviar global commit
senão:
escrever global abort no log
enviar global abort
```
---
# 2PC: Pseudocódigo do participante
```text
receber vote request
se puder confirmar:
escrever ready no log
enviar vote commit
aguardar decisão
senão:
escrever abort no log
enviar vote abort
se receber global commit:
confirmar
se receber global abort:
abortar
```
---