Perché le transazioni non impegnate devono essere annullate in ordine arretrato?


19

Ho un registro del database in cui alcune transazioni vincono (vengono impegnate prima dell'arresto anomalo) e altre perdono (non ancora impegnate). Abbiamo imparato in classe che le azioni dei perdenti devono essere annullate all'indietro.

C'è qualche motivo per farlo all'indietro? Qualcuno può dare un semplice esempio di un registro in cui le operazioni di annullamento in avanti darebbero risultati errati?


Questa domanda non dovrebbe essere posta in un altro sito più specifico?
nbro,

Risposte:


35

Transazioni originali:

  1. Inserisci record .r
  2. Aggiorna alcuni campi di .rfr

Annulla in avanti:

  1. Elimina record .r
  2. Invertire l'aggiornamento su - oh aspetta, non esiste più! Questo provoca un errore.rrr

Le cose devono essere annullate fisicamente individualmente in ordine inverso se il sistema è in grado di capire a quale stato devono essere ripristinate le cose e può applicare tutte le modifiche necessarie prima di elaborare qualcos'altro?
supercat

11
Annullare le modifiche in ordine inverso rende più semplice. Perché dovresti provare a renderti duro con te stesso?
gnasher729,

1
No, il sistema non farà tutto, ma lo capirà comunque nell'ordine arretrato.
Evil

3
In molti sistemi di database del mondo reale non farlo nemmeno in ordine inverso a causa dei vincoli chiave sulle tabelle.
SeanR

11

Per aggiungere alla risposta di DylanSp, il tentativo di aggiornare un campo in un record inesistente non riuscirà, ma il risultato sarà comunque il risultato previsto: il record r non esiste.

Tuttavia, considera una situazione in cui la cancellazione di un record in realtà fallirà:

  1. Inserisci ordine O.
  2. Inserisci la riga ordine L.

Supponiamo, non irrealisticamente, che ogni OrderLine debba essere correlato a un Ordine.

Ora il rollback della transazione a partire dall'eliminazione dell'Ordine fallirà perché ciò violerebbe la nostra regola aziendale.

Quindi dopo

  1. Elimina ordine O. (FAIL)
  2. Elimina ordineline L. (SUCCESSO)

Potremmo finire con un Ordine esistente (senza un Ordine).

Ovviamente, in questo caso potremmo usare una cancellazione a cascata, ma ciò significherebbe che il passaggio 2 fallirebbe (senza impatto). Peggio ancora, potrebbe essere un comportamento indesiderato implementare eliminazioni a cascata sugli ordini.


Va bene questo ha senso. Grazie per il tuo aiuto
prjctdth

È corretto presumere che i vincoli non siano stati violati prima o dopo la transazione in circostanze "normali"? Normalmente, intendo che la transazione non avrebbe avuto esito negativo se solo una persona stesse utilizzando il database. Se questo è vero, perché sarebbe importante non introdurre violazioni dei vincoli durante il processo di annullamento? Sembra che i vincoli potrebbero essere disattivati ​​all'inizio dell'annullamento e abilitati una volta completata l'operazione.
Noctis Skytower,

2
@NoctisSkytower La disattivazione dei vincoli durante una normale operazione di I / O li rende inutili. Esistono per un motivo. Il mio esempio illustra chiaramente come i vincoli possono essere soddisfatti in circostanze normali, ma violati durante il rollback. La disattivazione dei vincoli durante il rollback complica inutilmente le cose e risolve il problema sbagliato. Il problema non è il vincolo, il problema è la sua violazione tentando erroneamente di eseguire il rollback.
oerkelens,

Sì, ha senso, ma perché controllare i vincoli durante il rollback? Supponendo che i rollback siano progettati per essere completati senza problemi, perché perdere inutilmente tempo a controllare i vincoli se si sa che non verranno violati al termine del rollback? A proposito, quella dovrebbe essere una garanzia perché se un rollback fallisse, il DB apparentemente avrebbe bisogno di roll-forward che non può fare.
Noctis Skytower,

1
@NoctisSkytower dovrebbe essere impossibile che il DB si trovi mai in uno stato in cui i vincoli vengono violati, anche se si tratta di uno stato temporaneo. Se l' intero rollback è atomico, non importa quale ordine accada perché non esiste un ordine, è un'unica istruzione che "avviene tutto in una volta". se ci sono due o più transazioni che vengono ripristinate separatamente in un certo ordine, è obbligatorio che l'ordine sia tale che qualsiasi osservatore che legge i dati nel mezzo possa vedere solo una situazione in cui tutti i vincoli sono validi.
Peteris,

6

Andiamo per analogia: supponiamo che tu esca per cena.

  1. Metti le calze.
  2. Mettiti le scarpe.
  3. In piedi.
  4. Walk to door.

Quindi ricevi una telefonata. Piani della cena annullati.

  1. Togliti le calze.
  2. Togliti le scarpe.
  3. Siediti.
  4. Allontanati dalla porta.

C'è qualcosa che non va lì dentro. Puoi inciampare e ferirti. O più probabilmente, ti renderai conto che alcune azioni non possono essere annullate fino a quando le azioni successive non vengono annullate per prime.

Annullare l'ultima cosa che stavi facendo ti riporta a dove eri quando si è verificato l'ultimo passo. Quindi annulla quel passaggio e ripeti, tornando indietro fino a quando non rimane più nulla. D'altra parte, invertire il primo passo potrebbe non essere possibile dati gli stati che seguono i passi successivi.

matematicamente parlando: le azioni potrebbero non essere commutate, quindi ogni volta che importa quale passo fai prima o secondo, l'ordine in cui annulli i passaggi conta.


3

Questo è giusto perché le transazioni sono costruite l'una sull'altra e il risultato di una transazione dipende molto dalla situazione prima che fosse commessa.

Diamo un'occhiata alle transazioni finanziarie:

(all'inizio, prima che le transazioni ami debbano 100 USD)

  1. a mi deve 100 USD (ora debito totale 200)
  2. ariceve uno sconto del 10% su ciò che mi deve. (ora debito totale 180)

Diciamo che voglio annullare le due transazioni.

Se cancelliamo il primo, finiremo con:

  1. debito inferiore 100 (ora debito 80)
  2. annulla sconto del 10% (ora ha debito 80 / 0.9 = 88)

Questo è sbagliato, dobbiamo tornare al debito di 100. Sarà giusto se annulliamo le transazioni in ordine inverso.

  1. annulla sconto - ora il debito è 200
  2. abbassa 100 debiti - ora il debito è 100

2

Supponiamo che ci sia una tabella T con una sola colonna.

Supponiamo che il "registro di annullamento" sia un file di database che contenga transazioni senza commit e che il "registro di ripetizione" sia un file di database che contenga sia transazioni di commit che non di commit che non sono ancora state applicate ai file di dati.

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.

Perché ENTRAMBE le transazioni impegnate e non impegnate vengono scritte nel file di registro di ripristino? La ragione di ciò è fornire un recupero temporizzato.

Ciò significa che il contenuto del file "redo log" NON è coerente con la transazione. Per questo motivo, ogni volta che il registro di ripetizione viene utilizzato per applicare le transazioni impegnate ai file di dati, il "registro di annullamento" DEVE ANCHE essere utilizzato per ripristinare le transazioni non impegnate.

Perché le transazioni nel "registro di annullamento" vengono ripristinate nell'ordine inverso? La transazione 300 ha aggiunto 50 al valore esistente di ogni colonna di ogni riga. Pertanto, se la transazione 200 viene ripristinata per prima, i valori cambieranno da 251, 252 e da 253 a 201, 202 e 203. Se la transazione 300 venisse quindi ripristinata per ultima, i valori sarebbero 151, 152 e 153 - che non corrispondono i valori di commit originali.

RIFERIMENTI:

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


0

Non è intrinsecamente vero. Il rollback può semplicemente riapplicare i blocchi memorizzati nella cache di annullamento in modo che lo stato finale sia lo stesso dello stato iniziale. Poiché il registro è stato scritto in ordine di inoltro, il mio rollback è stato applicato anche in ordine di inoltro. L'ordine non importava affatto perché il rollback avrebbe riprovato fino a quando il file di registro non fosse stato contrassegnato come risolto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.