Por que as transações não confirmadas devem ser desfeitas na ordem inversa?

19

Eu tenho um log de banco de dados em que algumas transações vencem (elas são confirmadas antes da falha) e outras perdem (ainda não confirmadas). Aprendemos em sala de aula que as ações dos perdedores devem ser desfeitas para trás.

Existe alguma razão para fazer isso ao contrário? Alguém pode dar um exemplo simples de um log em que desfazer encaminhamentos daria resultados incorretos?

prjctdth
fonte
Essa pergunta não deve ser feita em outro site mais específico?
Nbro 14/07

Respostas:

35

Transações originais:

  1. Inserir registro .r
  2. Atualize algum campo de r .fr

Desfazer frente:

  1. Excluir registro .r
  2. Inverta a atualização para - oh espere, r não existe mais! Isso causa um erro.rr
DylanSp
fonte
As coisas precisam ser fisicamente desfeitas individualmente em ordem inversa, se o sistema puder descobrir em que estado as coisas precisam ser revertidas e aplicar todas as alterações necessárias antes de processar qualquer outra coisa?
Supercat
11
Desfazer alterações na ordem inversa facilita. Por que você tentaria dificultar a si mesmo?
gnasher729
1
Não, o sistema não fará tudo, mas ainda descobrirá isso na ordem inversa.
Mal
3
Em muitos sistemas de banco de dados do mundo real, fazê-lo não na ordem inversa nem seria possível devido a restrições importantes nas tabelas.
SeanR
11

Para adicionar à resposta do DylanSp, a tentativa de atualizar um campo em um registro não existente falhará, mas o resultado ainda será o esperado: o registro r não existe.

No entanto, considere uma situação em que a exclusão de um registro realmente falhará:

  1. Inserir pedido O.
  2. Inserir linha de pedido L.

Vamos supor, de maneira não irrealista, que todo OrderLine deve estar relacionado a um Pedido.

Agora, a reversão da transação começando com a exclusão do Pedido falhará, pois isso violaria nossa regra de negócios.

Então depois

  1. Excluir pedido O. (FAIL)
  2. Excluir Ordeline L. (SUCCESS)

Podemos terminar com um pedido existente (sem uma linha de pedido).

Obviamente, nesse caso, poderíamos usar uma exclusão em cascata, mas isso significaria que a etapa 2 falharia (sem impacto). Pior, pode ser um comportamento indesejável implementar exclusões em cascata nos pedidos.

oerkelens
fonte
Ok, isso faz sentido. Thx for your help
prjctdth
É adequado assumir que as restrições não foram violadas antes ou depois da transação em circunstâncias "normais"? Normalmente, quero dizer que a transação não teria falhado se apenas uma pessoa estivesse usando o banco de dados. Se isso for verdade, por que seria importante não introduzir violações de restrição durante o processo de desfazer? Parece que as restrições podem ser desativadas no início do desfazer e ativadas quando a operação estiver concluída.
Noctis Skytower
2
@NoctisSkytower Desativar restrições durante uma operação normal de E / S as torna inúteis. Eles existem por uma razão. Meu exemplo ilustra claramente como as restrições podem ser atendidas em circunstâncias normais, mas violadas durante a reversão. Desativar restrições durante a reversão está complicando desnecessariamente os problemas e corrigindo o problema errado. O problema não é a restrição, o problema é a violação ao tentar reverter incorretamente.
oerkelens
Sim, isso faz sentido, mas por que verificar restrições durante a reversão? Supondo que as reversões foram projetadas para garantir a conclusão sem problemas, por que perder tempo desnecessariamente verificando as restrições se é sabido que elas não serão violadas no momento em que a reversão for concluída? BTW, isso deve ser uma garantia porque, se uma reversão falhar, o banco de dados aparentemente precisará avançar, o que não pode fazer.
Noctis Skytower
1
@NoctisSkytower, deve ser impossível que o banco de dados esteja em um estado em que as restrições sejam violadas, mesmo que seja temporário. Se toda a reversão for atômica, não importa em que ordem ocorre, porque não há ordem, é uma única instrução que "acontece de uma só vez". se houver duas ou mais transações que são revertidas separadamente em alguma ordem, é obrigatório que a ordem seja tal que qualquer observador que esteja lendo os dados no meio possa ver apenas uma situação em que todas as restrições se mantêm.
31416 Peteris
6

Vamos por analogia: diga que você está saindo para jantar.

  1. Coloque as meias.
  2. Coloque os sapatos.
  3. Levante-se.
  4. Caminhe até a porta.

Então você recebe uma ligação. Planos de jantar cancelados.

  1. Tire as meias.
  2. Tire os sapatos.
  3. Sentar-se.
  4. Afaste-se da porta.

Algo dá errado lá. Você pode tropeçar e se machucar. Ou, mais provavelmente, você perceberá que algumas ações não podem ser desfeitas até que ações posteriores sejam desfeitas primeiro.

Desfazer a última coisa que você estava fazendo leva você de volta para onde estava quando ocorreu a penúltima etapa. Em seguida, você desfaz essa etapa e repete, voltando até que nada reste. Por outro lado, a reversão da primeira etapa pode não ser possível, considerando os estados que seguem as etapas posteriores.

matematicamente falando: as ações podem não ser comutadas; portanto, sempre que importa qual etapa você executa primeiro ou segundo, a ordem na qual você desfaz as etapas será importante.

Joel
fonte
3

Isso é certo porque as transações são construídas umas sobre as outras e o resultado de uma transação depende muito da situação antes de ser confirmada.

Vejamos as transações financeiras:

(no início, antes das transações ame deverem 100 USD)

  1. a me deve 100 USD (agora dívida total 200)
  2. arecebe 10% de desconto sobre o que ele me deve. (agora dívida total 180)

Digamos que eu queira cancelar as duas transações.

Se cancelarmos o primeiro primeiro, terminaremos com:

  1. dívida mais baixa 100 (agora tem dívida 80)
  2. cancelar desconto de 10% (agora tem dívida 80 / 0,9 = 88)

Isso está errado, precisamos voltar à dívida de 100. Isso será correto se cancelarmos as transações na ordem inversa.

  1. cancelar desconto - agora a dívida é 200
  2. menor dívida 100 - agora dívida é 100
thebeancounter
fonte
2

Suponha que exista uma tabela T com apenas uma coluna.

Suponha que o "desfazer log" é um arquivo de banco de dados que contém transações não confirmadas e que o "refazer log" é um arquivo de banco de dados que contém transações confirmadas e não confirmadas que ainda não foram aplicadas aos arquivos de dados.

At 8:00 A.M., Transaction 100 inserts rows with values 101, 102 and 103 into table T. At 8:10 A.M., Transaction 100 is committed and the commit for transaction 100 completes. At 8:15 A.M., Transaction 200 updates row 101 to 201, 102 to 202 and 103 to 203. At 8:20 A.M., Transaction 200 has not been committed and remains in the undo log of the database. At 8:25 A.M., Transaction 300 increments each row by 50, changing row 201 to 251, 202 to 252, and 203 to 253. At 8:30 A.M., Transaction 300 has not been committed and remains in the undo log of the database. At 8:35 A.M., The instance providing access to the database crashes.

At 8:40 A.M., The instance is restarted, and the database files are opened as the instance is started:

              The committed values in T are still 101, 102 and 103.

              Since 201, 202, and 203, and 251, 252 and 253
              are not committed, if they are written into the "redo
              log" of the database, there is a need to "roll back"
              the transactions AFTER the "redo log" is applied.

              Since 201, 202, and 203, and 251, 252 and 253
              are not committed, they are in the "undo log"
              of the database.

              The undo log of the database is used BOTH to (1) roll
              back a transaction that is deliberately rolled 
              back in the memory structure of the database instance, 
              and also (2) during the instance recovery at 8:40 A.M.

At 8:41 A.M., The redo log has been applied, and the T table contains values 251, 252 and 253 in the instance memory.

              The undo log has not yet been applied.

At 8:42 A.M., The undo log is applied in the reverse order: Uncommitted transaction 300 is undone, and Uncommitted transaction 200 is undone.

Por que ambas as transações confirmadas e não confirmadas são gravadas no arquivo de log refazer? A razão para isso é fornecer recuperação point-in-time.

Isso significa que o conteúdo do arquivo "refazer log" NÃO é consistente com as transações. Por esse motivo, sempre que o redo log for usado para aplicar transações confirmadas aos arquivos de dados, o "desfazer log" DEVE TAMBÉM ser usado para reverter transações não confirmadas.

Por que as transações no "desfazer log" são revertidas na ordem inversa? A transação 300 adicionou 50 ao valor existente de cada coluna de cada linha. Portanto, se a transação 200 for revertida primeiro, os valores serão alterados de 251, 252 e 253 para 201, 202 e 203. Se a transação 300 fosse revertida por último, os valores seriam 151, 152 e 153 - que não correspondem os valores comprometidos originais.

REFERÊNCIAS:

https://asktom.oracle.com/pls/asktom/f?p=100:11.0:::: P11_QUESTION_ID:1670195800346464273

AB
fonte
0

Não é inerentemente verdade. A reversão pode simplesmente reaplicar os blocos que foram armazenados em cache no log de desfazer, para que o estado final seja o mesmo que o estado inicial. Como o log foi gravado na ordem de encaminhamento, eu fiz minha reversão também ser aplicada na ordem de encaminhamento. O pedido não importava porque a reversão tentaria novamente até que o arquivo de log fosse marcado como resolvido.

Joshua
fonte