Dlaczego niezatwierdzone transakcje muszą być cofane w kolejności wstecznej?

19

Mam dziennik bazy danych, w którym niektóre transakcje wygrywają (są zatwierdzane przed awarią), a niektóre tracą (jeszcze nie zatwierdzone). W klasie nauczyliśmy się, że działania przegranych muszą zostać cofnięte.

Czy jest jakiś powód, aby robić to wstecz? Czy ktoś może podać prosty przykład dziennika, w którym cofanie w przód dawałoby błędne wyniki?

prjctdth
źródło
Czy nie należy zadawać tego pytania na innej, bardziej szczegółowej stronie?
nro

Odpowiedzi:

35

Oryginalne transakcje:

  1. Wstaw rekord .r
  2. Zaktualizuj niektóre pola z r .far

Cofnij do przodu:

  1. Usuń rekord .r
  2. Odwróć aktualizację do - och, czekaj, r już nie istnieje! To powoduje błąd.rr
DylanSp
źródło
Czy rzeczy muszą zostać fizycznie indywidualnie cofnięte w odwrotnej kolejności, jeśli system może dowiedzieć się, w jakim stanie rzeczy trzeba przywrócić i zastosować wszystkie niezbędne zmiany przed przetworzeniem czegokolwiek innego?
supercat
11
Cofanie zmian w odwrotnej kolejności ułatwia. Dlaczego próbujesz utrudnić sobie życie?
gnasher729,
1
Nie, system nie zrobi wszystkiego, ale nadal odkryje to w odwrotnej kolejności.
Zły
3
W wielu rzeczywistych systemach baz danych robienie tego w odwrotnej kolejności nie byłoby nawet możliwe z powodu kluczowych ograniczeń tabel.
SeanR
11

Aby dodać do odpowiedzi DylanSp, próba aktualizacji pola w nieistniejącym rekordzie zakończy się niepowodzeniem, ale wynikiem będzie nadal oczekiwany wynik: rekord r nie istnieje.

Rozważ jednak sytuację, w której usunięcie rekordu faktycznie się nie powiedzie:

  1. Wstaw zamówienie O.
  2. Wstaw wiersz zamówienia L.

Załóżmy, nie nierealnie, że każda linia zamówienia musi być powiązana z zamówieniem.

Cofanie transakcji, zaczynając od usunięcia Zamówienia, zakończy się niepowodzeniem, ponieważ naruszałoby to naszą zasadę biznesową.

Więc później

  1. Usuń zamówienie O. (FAIL)
  2. Usuń Ordeline L. (SUKCES)

Możemy skończyć z istniejącym Zamówieniem (bez Linii Zamówień).

Oczywiście w tym przypadku moglibyśmy użyć kaskadowego usuwania, ale oznaczałoby to, że krok 2 nie powiedzie się (bez wpływu). Co gorsza, wdrażanie kaskadowego usuwania zleceń może być niepożądane.

oerkelens
źródło
Ok, to ma sens. Thx za pomoc
prjctdth
Czy należy założyć, że ograniczenia nie zostały naruszone przed transakcją lub po niej w „normalnych” okolicznościach? Mam na myśli, że transakcja nie powiodłaby się, gdyby tylko jedna osoba korzystała z bazy danych. Jeśli to prawda, dlaczego tak ważne jest, aby nie wprowadzać naruszeń ograniczeń podczas procesu cofania? Wygląda na to, że ograniczenia można wyłączyć na początku cofania i włączyć po zakończeniu operacji.
Noctis Skytower
2
@NoctisSkytower Wyłączenie ograniczeń podczas normalnej operacji we / wy czyni je bezużytecznymi. Istnieją z jakiegoś powodu. Mój przykład wyraźnie pokazuje, w jaki sposób ograniczenia mogą być spełnione w normalnych okolicznościach, ale naruszone podczas wycofywania. Wyłączenie ograniczeń podczas wycofywania jest niepotrzebnie komplikujące sprawy i rozwiązuje zły problem. Problem nie jest ograniczeniem, problemem jest naruszenie go przez niepoprawną próbę wycofania.
oerkelens
Tak, to ma sens, ale po co sprawdzać ograniczenia podczas wycofywania? Zakładając, że wycofanie ma na celu zagwarantowanie, że zakończy się ono bez problemu, dlaczego niepotrzebnie marnujesz ograniczenia sprawdzania czasu, jeśli wiadomo, że nie zostaną naruszone do czasu zakończenia wycofywania? BTW, to powinno być gwarancją, ponieważ jeśli wycofanie nie powiedzie się, DB najwyraźniej będzie musiało przejść do przodu, czego nie może zrobić.
Noctis Skytower
1
@NoctisSkytower, DB nie powinno być w stanie, w którym naruszone są ograniczenia, nawet jeśli jest to stan tymczasowy. Jeśli całe wycofywanie jest atomowe, to nie ma znaczenia, jaki będzie porządek, ponieważ nie ma porządku, jest to pojedyncza instrukcja, która „dzieje się naraz”. jeśli istnieją dwie lub więcej transakcji, które są wycofywane osobno w pewnej kolejności, wówczas nakaz jest taki, aby każdy obserwator odczytujący dane w środku widział tylko sytuację, w której wszystkie ograniczenia są spełnione.
Peteris,
6

Przejdźmy przez analogię: powiedz, że idziesz na obiad.

  1. Załóż skarpetki.
  2. Załóż buty.
  3. Wstań.
  4. Idź do drzwi.

Potem dostaniesz telefon. Plany obiadowe anulowane.

  1. Zdejmij skarpetki.
  2. Zdejmij buty.
  3. Usiądź.
  4. Odejdź od drzwi.

Coś tam idzie nie tak. Możesz się potknąć i zranić. Lub bardziej prawdopodobne, zdasz sobie sprawę, że niektórych działań nie można cofnąć, dopóki późniejsze działania nie zostaną cofnięte w pierwszej kolejności.

Cofanie ostatniej rzeczy, którą robiłeś, powoduje powrót do miejsca, w którym się znajdowałeś, kiedy nastąpił następny krok. Następnie cofnij ten krok i powtórz, cofając się, dopóki nic nie zostanie. Z drugiej strony cofanie pierwszego kroku może nie być możliwe, biorąc pod uwagę stany następujące po nim.

z matematycznego punktu widzenia: czynności mogą się nie zamieniać, więc zawsze, gdy ma znaczenie to, który krok zrobisz pierwszy lub drugi, kolejność cofania kroków będzie miała znaczenie.

Joel
źródło
3

Jest to słuszne, ponieważ transakcje są budowane jeden na drugim, a wynik transakcji w dużej mierze zależy od sytuacji przed jej popełnieniem.

Spójrzmy na transakcje finansowe:

(na początku, zanim transakcje będą ami winne 100 USD)

  1. a jest mi winien 100 USD (obecnie całkowity dług 200)
  2. aotrzymuje 10% zniżki na to, co jest mi winien. (teraz całkowity dług 180)

Powiedzmy, że chcę anulować dwie transakcje.

Jeśli anulujemy pierwszy, otrzymamy:

  1. niższe zadłużenie 100 (teraz mają dług 80)
  2. anuluj 10% zniżki (teraz masz dług 80 / 0,9 = 88)

To źle, musimy wrócić do długu w wysokości 100. To będzie słuszne, jeśli anulujemy transakcje w odwrotnej kolejności.

  1. anuluj rabat - teraz dług wynosi 200
  2. obniż 100 długów - teraz dług wynosi 100
thebeancounter
źródło
2

Załóżmy, że istnieje tabela T z tylko jedną kolumną.

Załóżmy, że „dziennik cofania” to plik bazy danych zawierający niezatwierdzone transakcje i że „dziennik ponawiania” to plik bazy danych zawierający zarówno niezatwierdzone, jak i zatwierdzone transakcje, które nie zostały jeszcze zastosowane do plików danych.

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.

Dlaczego ZARÓWNO zatwierdzone i niezaangażowane transakcje są zapisywane w pliku dziennika ponawiania? Powodem tego jest odzyskanie punktu w czasie.

Oznacza to, że zawartość pliku „redo log” NIE jest zgodna z transakcjami. Z tego powodu, ilekroć dziennik ponawiania jest używany do zastosowania zatwierdzonych transakcji do plików danych, „Cofnij dziennik” MUSI SIĘ RÓWNIEŻ używać do wycofania niezatwierdzonych transakcji.

Dlaczego transakcje w „dzienniku cofania” są wycofywane w odwrotnej kolejności? Transakcja 300 dodała 50 do istniejącej wartości każdej kolumny każdego wiersza. Dlatego jeśli transakcja 200 zostanie wycofana jako pierwsza, wartości zmienią się z 251, 252 i 253 na 201, 202 i 203. Jeśli transakcja 300 zostanie następnie wycofana jako ostatnia, wartości wyniosą 151, 152 i 153 - które nie pasują oryginalne zatwierdzone wartości.

BIBLIOGRAFIA:

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

AB
źródło
0

To nie jest z natury prawda. Wycofanie może po prostu ponownie zastosować bloki, które były buforowane w dzienniku cofania, aby stan końcowy był taki sam jak stan początkowy. Ponieważ dziennik został napisany w kolejności przekazywania, postanowiłem, że moje wycofanie będzie obowiązywać również w kolejności przekazywania. Kolejność nie ma znaczenia, ponieważ wycofanie będzie ponawiać, dopóki plik dziennika nie zostanie oznaczony jako rozliczony.

Jozuego
źródło