Transakcje i blokady

0

Pilnie poszukuję materiałów, które ukazałyby mi praktyczne zastosowania transakcji i blokad np. w MySQLu. Niestety w sieci znalazłem tylko teoretyczne podejście do tego tematu, nigdzie nie znalazłem praktycznego zastosowania. Może zna ktoś jakąś książkę, w której zostałoby to w miarę dobrze opisane?

0

klasyczny przykład - masz fakturę, osobno zapisujesz nagłówek i osobno każdą pozycję - w większości przypadków nie da się tego zrobić jednym insertem. Teraz stajesz przed problemem, że faktura jeśli się zapisze to MUSI być cała w bazie. Nie może być tek, że zapiszą się pozycje 1 i 3 a 2 nie (bo np. pozycja 2 nie miała ceny w kartotece). Możesz po każdym insercie sprawdzać czy się udał, i jak nie to kasować to co już się dodało ale potem trzeba sprawdzić czy kasowanie się udało. Itd., itp. Zamiast się tak bawić możesz przed pierwszym zapisem rozpocząć transakcję, po ostatnim zapisie ją zatwierdzić i jeśli zatwierdzenie przebiegnie bez problemów to masz PEWNOŚĆ, że wszystkie dane się zapisały - gwarantuje Ci to sam mechanizm transakcji. Jeśli podczas zatwierdzania transakcji wystąpi błąd to po prostu odwołujesz całą transakcję i też masz pewność, że nic się nie zapisało. Co więcej można tak ustawić mechanizm transakcji, że w przypadku np. zerwania połączenia są automatycznie wycofywane. Więc jeśli w połowie wypisywania faktury zawiesi Ci się komputer to po pierwsze trzeba ją będzie całą wklepać raz jeszcze ale jednocześnie nic nie zostanie z poprzedniej, nie zostanie dziura w numeracji (o ile numerowanie faktur jest rozwiązane w odpowiedni sposób a nie przez autoinc)

0

A jak to wygląda z blokadami?

1

Transakcje są realizowane czasami za pomocą two-phase-locking czyli za pomocą blokad. Jak? Ano tak, że jeśli w danej transakcji są modyfikowane jakieś rekordy to wcześniej trzeba te rekordy "zablokować" tak żeby tylko jedna transakcja na raz mogła je zmieniać (oczywiście to jest dużo bardziej skomplikowane w praktyce i zależy też od poziomu izolacji transakcji).

0
tomekz1991 napisał(a):

A jak to wygląda z blokadami?

najprostsza blokada to właśnie w transakcji zrobienie albo pustego update (np. update dupa set id=id where id = 3 - nic tak naprawdę nie zmieniasz ale baza blokuje rekord) albo zrobienie select for update (analogicznie jak z update będzie to np. select id from dupa where id=3 for update). I teraz dopóki nie zrobisz commit lub rollback na transakcji, w której zrobiłeś któreś z powyższych to nikt inny nie zmieni rekordu. Tutaj są jeszcze dwie wersje jak zachowa się próba zablokowania już zablokowanego rekordu. Jeśli transakcja ma ustawioną opcję nowait to próba blokady już zablokowanego rekordu zakończy się błędem. Jeśli nie ma to po prostu transakcja będzie czekała aż ta, która teraz blokuje się skończy i wtedy ona zablokuje rekord.
Jak to działa w praktyce - np. chcemy edytować fakturę ale tak aby nikt inny nie mógł w międzyczasie nic zmienić.

  1. Ustawiamy nowait transakcji i ją rozpoczynamy
  2. Po wybraniu opcji edycji faktury a przed pokazaniem okna próbujemy zrobić pusty update lub select for update na konkretnym rekordzie, który trzyma nagłówek naszej faktury
  3. Jeśli pkt 2 się powiedzie to faktura jest nasza i pokazujemy okno edycji
  4. Jeśli pkt 2 zawiedzie to pokazujemy info, że ktoś edytuje już fakturę
  5. Po zakończeniu edycji w zależności czy user chce zapisać zmiany robimy commit lub jak nie chce to rollback

To jest blokowanie pesymistyczne i to w najprostszej postaci. Można rozszerzyć tą opcję o np. automatyczne anulowanie transakcji po np. 10 minutach bezczynności usera aby inni mogli się dostać do rekordu. Można też dodatkowo zapisywać kto (np. login, nazwę kompa) edytuje dany rekord i takie informacje pokazywać tym, którzy chcą się do tego rekordu dostać.

Powyższe można zrealizować też "ręcznie", tzn. zamiast mechanizmu transakcji stosować własne znaczniki, że dany rekord jest zablokowany ale jak dla mnie plusów nie ma to żadnych a trzeba się mocno napracować aby było to niezawodne.

Drugi sposób blokowania rekordu to blokowanie optymistyczne. Działa to tak, że nie zakłada się blokady w momencie rozpoczęcia edycji. Jednocześnie dany rekord może mieć otwartych do edycji wiele osób. Zapisuje pierwszy, a każdy następny zanim zapisze zmiany to sprawdza czy rekord się nie zmienił od czasu rozpoczęcia edycji i jeśli nie to zapisujemy a jeśli tak to albo pytamy usera co zrobić (z np. możliwością pokazania jak teraz wygląda rekord) albo odrzucamy zmiany.

Trzeci sposób to tzw. "ostatni wygrywa" - ten kto ostatni zapisze tego zmiany zostają (nadpisuje zmiany wszystkich innych, którzy edytowali ten rekord "w tym samym czasie")

To w jaki sposób zapewnimy wielodostęp do danych i jak będziemy się bronić przed jednoczesną modyfikacją tego samego rekordu zależy w dużym stopniu od charakteru danych, które obrabiamy. Może być nawet tak, że w jednej aplikacji będziemy mieli do czynienia ze wszystkimi trzema sposobami blokowania. Np. realizacja zamówienia jako blokowanie pesymistyczne (bo jak ktoś kompletuje towar dla danego zamówienia to nikt inny nie powinien kompletować tego samego zamówienia), edycja kontrahenta jako blokowanie optymistyczne bo jak to czasami w biurze ktoś sobie otworzy kontrahenta do edycji i idzie na kawę/fajkę/WC i taka edycja sobie wisi i 3h natomiast pod "ostatni wygrywa" można podpiąć np. sytuację, gdzie mamy kilka maszyn, które zasypują nas danymi, które czasem mogą się dublować i zależy nam aby mieć tylko najświeższą wersję danych, niezależnie z której maszyny one pochodzą. To są tylko przykłady i to dość naciągane :) więc się nie czepiać

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0