Commit fail scenario

PR
  • Rejestracja:prawie 4 lata
  • Ostatnio:11 minut
  • Postów:222
0

Scenariusz:
Wołam dbTransaction.commit() w apce, dane docierają do bazy, ta je zapisuje z sukcesem, więc chce wysłać do apki wiadomość, powiodło się, ale ta nie odpowiada np. zaliczyła crash.

Jak różne bazy danych radzą sobie z tym, macie jakieś dobre źródło do poczytania?

To samo pytanie dotyczy się wszelkiej maści brokerów, ale zarówno dla produkcji jak i konsumpcji: RabbitMQ, Kafka (acknowledgment)

Chodzi mi głównie o techniczne mięsko, ale także big picture, chciałbym w końcu usystematyzować wiedzę w tym zakresie. :)

edytowany 1x, ostatnio: Productionserver
hzmzp
  • Rejestracja:ponad 11 lat
  • Ostatnio:około 8 godzin
  • Postów:632
0

Zależne bardzo od rozwiązania i jego konfiguracji, aczkolwiek wysłanie commit wiąże się z zapisem i nie ma znaczenia czy apka padnie czy nie. Wyjątkiem może tu być Two-Phase Commit (2PC) przy systemach rozproszonych.

A3
  • Rejestracja:6 miesięcy
  • Ostatnio:około 22 godziny
  • Postów:35
1

Wołam dbTransaction.commit() w apce, dane docierają do bazy, ta je zapisuje z sukcesem, więc chce wysłać do apki wiadomość, powiodło się, ale ta nie odpowiada np. zaliczyła crash.

Trochę to nie jasne dla mnie co napisałeś. Chodzi o sytuacje że baza danych scommitowała zmiane a na froncie potem pojawił się błąd?

To samo pytanie dotyczy się wszelkiej maści brokerów, ale zarówno dla produkcji jak i konsumpcji: RabbitMQ, Kafka (acknowledgment)

Transactional Outbox/Inbox Pattern, SAGA

YA
  • Rejestracja:około 10 lat
  • Ostatnio:około 3 godziny
  • Postów:2371
0

Wołam dbTransaction.commit() w apce, dane docierają do bazy, ta je zapisuje z sukcesem, więc chce wysłać do apki wiadomość, powiodło się, ale ta nie odpowiada np. zaliczyła crash.

A skąd konkretnie chcesz wysłać i dokąd i w jaki sposób?

Jak chcesz big picture, to doczytaj o tym w jaki sposób integruje się komponenty, w szczególności o:
a) modelach komunikacji: synchroniczny, asynchroniczny
b) blocking vs non-blocking
c) message flow, np. REQ-RES, REQ-ACK-RES, REQ-ACK-RES-ACK

loza_prowizoryczna
loza_prowizoryczna
d) good enough e) duct tape
PR
c) doczytam, polecisz coś?
PR
  • Rejestracja:prawie 4 lata
  • Ostatnio:11 minut
  • Postów:222
0
Aleksander-32 napisał(a):

Wołam dbTransaction.commit() w apce, dane docierają do bazy, ta je zapisuje z sukcesem, więc chce wysłać do apki wiadomość, powiodło się, ale ta nie odpowiada np. zaliczyła crash.

Trochę to nie jasne dla mnie co napisałeś. Chodzi o sytuacje że baza danych scommitowała zmiane a na froncie potem pojawił się błąd?

To samo pytanie dotyczy się wszelkiej maści brokerów, ale zarówno dla produkcji jak i konsumpcji: RabbitMQ, Kafka (acknowledgment)

Transactional Outbox/Inbox Pattern, SAGA

Nie, chodzi o specyficzną sytuację, co się dzieje, gdy umrze Ci połączenie pomiędzy serwerem (np. zwykłe REST API) a bazą danych, gdy db sobie już zrzuci na dane dysk, zrobi commit po swojej stronie i chce wysłać informację do klienta, że się powiodło. Tam są różne sztuczki z przywracaniem log transaction, zależnie od implementacji, tej wiedzy szukam.

Ten sam problem przy np. produkowaniu wiadomości (MQ), wysyłasz ACK, broker robi swoje i nie dostajesz zwrotki, bo zerwane połączenie z serwerem (np. crash maszyny, sieć zdechła itd.)

Zobacz pozostałe 66 komentarzy
KL
Pyrzpomnę że wątek jest o tym jak zachowuje się baza w takiej sytuacji. W szczególności wątek nie jest o tym jak bazy zapewniają spójność w przypadku replikacji, ani w jaki sposób od strony aplikacyjnej można zapewnić at-most-once execution, co umożliwia Transaction Guard, albo prosty constraint na bazie (w zależności od poziomu skomplikowania transkacji), ani at-least-once execution.
KL
loza_prowizoryczna
loza_prowizoryczna
No, pat - Jak ci baza umrze to będziesz miał zerwane połączenie. A w tym przypadku rozsądny klient (albo sterownik połączenia z bazą) powinien je ponowić z prośbą o powtórzenie ostatniej kolejki poleceń i wyników. Oczywiście to nie gwarantuje ci 100% skuteczności ale w tej rzeczywistości nic ci tego nie gwarantuje więc?
PR
mówimy tu o nagłej śmierci klienta
loza_prowizoryczna
loza_prowizoryczna
O umarłych cicho albo wcale. Jak powstanie z martwych to się dowie. Jak nie powstanie to nikogo to nie obchodzi.
YA
  • Rejestracja:około 10 lat
  • Ostatnio:około 3 godziny
  • Postów:2371
1

@Productionserver co do lektury, to klasyk: Enterprise Integration Patterns, REQ-ACK-RES-ACK wpadają pod https://www.enterpriseintegrationpatterns.com/patterns/conversation/

W przypadku, który opisujesz masz do czynienia z unreliable network (klient wysłał commit'a, padło połączenie i nie wiadomo jaki jest stan transakcji, może się udała, a może nie) i jest to jeden z problemów systemów rozproszonych. Szukaj pod hasłami "reliable messaging in distributed systems" ;-)

KL
  • Rejestracja:około rok
  • Ostatnio:36 minut
  • Postów:482
3

Ale o jakich outboxach czy sagach wy tutaj piszecie?

Pytanie jak dla mnie jest proste (nie mylić z tym czy odpowiedź jest prosta) - czy jak robisz COMMIT to baza fizycznie utrwala dane w transaction logu dopiero jak uda się zwrócić informację do klienta o sukcesie czy utrwala, a zwrócenie informacji to sprawa drugorzędna. Czy Kafka czy RabbitMQ to zachowanie będzie analogiczne bo z tego co wiem one pod spodem też korzystają z mechanizmu write ahead log.

Według mnie utrwala, a zwrócenie odpowiedzi do klienta jest best-effort, bo na logikę jak ma to się zachować w pierwszej opcji, zwróciłeś odpowiedź do klienta, a później nie udało się jednak tego commita zatwierdzić i co powinno się wydarzyć?

To są jakieś przypadki brzegowe, ale jak poszedł commit transakcji, a nie udało się zwrócić odpowiedzi do klienta to klient przy ponawianiu operacji powinien być w stanie taką sytuację obsłużyć.

SL
  • Rejestracja:około 7 lat
  • Ostatnio:20 minut
  • Postów:901
1

Zrobiłeś COMMIT to się wykonało. To co opisujesz jest niemożliwe do zaimplementowania, bo aplikacja musiałaby w nieskończoność komunikować się z bazą

  • zrób COMMIT, ale upewnij się, że żyję
  • spoko, czy żyjesz?
  • tak zrób COMMIT, ale upewnij się, że żyję
  • ...

Jak chcesz zrobić coś zaraz po COMMIcie to musisz wszystko zaimplementować asynchronicznie. Przykładowo masz inny proces, który czyta informacje z bazy danych i wysyła je do jakiegoś Rabbita. W większości przypadków ludzie olewają temat i wystarczy dobry graceful shutdown

Zobacz pozostałe 4 komentarze
KL
No @Productionserver twierdzi że baza zrobi rollback jak udało się zrobić commit ale połączenie się po tym zerwało i klient nie dostał potwierdzenia. Według mnie nie zrobi w takiej sytuacji.
SL
@Klaun: to co mówisz jest niemożliwe do zaimplementowania. Gdzieś przy commicie baza danych musi ustawić flagę, że dana transakcja jest zcommitowana. Pomiędzy sprawdzeniem stanu połączenia a ustawieniem tej flagi jest okno czasowe, gdzie połączenie i tak może się zerwać. To nie jest problem implementacji tylko klasyczny problem dwóch generałów. Szczerze mówiąc nie wiem jak jest. Pytałem ChatGPT i potwierdza moje słowa (ale czy można mu ufać). Swój wywód biorę stąd, że nie widzę opcji jak wersja OPa może być fizycznie zaimplementowana
KL
No to chyba niemożliwe jest to co pisze @Productionserver
PR
@Klaun: z tym timeoutem, to jest tak, leci db.commit() i masz tak niewydajne query, ze apka juz nie czeka i sama zrywa polaczenie, baza moze w tym czasie wlasnie juz commitowac zmiany, wiec problem jest podobny. To moja intuicja, z checia poznam suche fakty, jesli jestem w bledzie
PR
@slsy: wlasnie DB stosuja mechanizm WAL i potem robia jakas magie pod spodem, zeby to ogarnac, przynajmniej to mi sie gdzies kiedys przewinelo
KE
  • Rejestracja:ponad 6 lat
  • Ostatnio:około 2 godziny
  • Postów:684
0

Wołam dbTransaction.commit() w apce, dane docierają do bazy, ta je zapisuje z sukcesem, więc chce wysłać do apki wiadomość, powiodło się, ale ta nie odpowiada np. zaliczyła crash.
Jak różne bazy danych radzą sobie z tym, macie jakieś dobre źródło do poczytania?

To pytanie nie ma sensu, bo w momencie gdy apka zaliczyła crash, baza danych już dawno zapisała transakcję, wedle twojego scenariusza. Nie da się odpowiedzieć "jak sobie baza danych z tym radzi" - bo z jej punktu widzenia nie ma żadnego problemu, wszystko działa - poszedł commit i nara. To że potem w aplikacji poszedł jakiś exception w ogóle nie interesuje bazy danych.

KL
Ogólnie to się zgadzam, ale tutaj nie chodzi o scenariusz gdzie baza zapisała, a apka w kolejnej linijce się wywaliła, tylko baza zapisała, chciała wysłać odpowiedź w ramach otwartego połączenia, ale w tym momencie apka się scrashowała.
KE
Fakt, teraz zrozumiałem :) okej, dzięki, nie zauważyłem.
RequiredNickname
  • Rejestracja:prawie 5 lat
  • Ostatnio:około 4 godziny
  • Postów:620
1
  1. wysyłasz dane do DB
  2. potem z poziomu aplikacji robisz commit
  3. baza zapisuje dane
  4. zwraca info do klienta -> następuje zerwanie połączenia http/aplikacja robi crash (cokolwiek)

Dane dalej w DB są, to że klient się wywalił jej nie interesuje.

Albo ja czegoś nie rozumiem albo opisujesz wyimaginowany problem.
Tzn przypuszczam że po stronie bazy fizyczne zapisanie danych jest całkowicie odseparowane od mechaniki odpowiedzi (może nawet dzieje się to synchronicznie).

Ciężko jest mi sobie wyobrazić że jakiś produkcyjny silnik bazodanowy doprowadzi do niespójności tylko dlatego że wysypało sie na poziomie zwrotki do klienta.

Zarejestruj się i dołącz do największej społeczności programistów w Polsce.

Otrzymaj wsparcie, dziel się wiedzą i rozwijaj swoje umiejętności z najlepszymi.