Blokowanie optymistyczne a pesymistyczne

571

Rozumiem różnice między optymistycznym a pesymistycznym blokowaniem. Czy ktoś mógłby mi teraz wyjaśnić, kiedy używałbym jednego z nich w ogóle?

I czy odpowiedź na to pytanie zmienia się w zależności od tego, czy do wykonania zapytania używam procedury składowanej?

Ale tylko dla sprawdzenia, optymizm oznacza „nie blokuj stołu podczas czytania”, a pesymistyczny oznacza „blokuj stół podczas czytania”.

Jason Baker
źródło
1
blog.couchbase.com/…
Frank Myat Thu
1
To dobre pytanie, zwłaszcza że w serializacji czytałem At any technique type conflicts should be detected and considered, with similar overhead for both materialized and non-materialized conflicts.
Little Alien,
1
Tutaj możesz znaleźć dobre wyjaśnienie, tutaj na SO, na czym polega podstawowa koncepcja optymistycznego blokowania .
Diego Mazzaro,

Odpowiedzi:

812

Optymistyczne blokowanie to strategia polegająca na czytaniu rekordu, zapisywaniu numeru wersji (inne metody do tego celu obejmują daty, znaczniki czasu lub sumy kontrolne / skróty) i sprawdzaniu, czy wersja nie uległa zmianie przed ponownym zapisaniem rekordu. Kiedy zapisujesz rekord z powrotem, filtrujesz aktualizację do wersji, aby upewnić się, że jest atomowa. (tzn. nie został zaktualizowany między sprawdzeniem wersji i zapisaniem rekordu na dysku) a aktualizacją wersji za jednym razem.

Jeśli zapis jest brudny (tzn. Inna wersja niż Twoja), przerywasz transakcję, a użytkownik może ją ponownie uruchomić.

Strategia ta ma największe zastosowanie do systemów o dużej objętości i architektur trójwarstwowych, w których niekoniecznie utrzymuje się połączenie z bazą danych dla sesji. W tej sytuacji klient nie może faktycznie utrzymywać blokad bazy danych, ponieważ połączenia są pobierane z puli i możesz nie używać tego samego połączenia z jednego dostępu do drugiego.

Blokowanie pesymistyczne ma miejsce, gdy blokujesz rekord na wyłączny użytek, dopóki go nie skończysz. Ma znacznie lepszą integralność niż optymistyczne blokowanie, ale wymaga ostrożności podczas projektowania aplikacji, aby uniknąć Deadlocks . Aby użyć blokowania pesymistycznego, potrzebujesz albo bezpośredniego połączenia z bazą danych (jak to zwykle bywa w przypadku dwupoziomowej aplikacji serwera klienta ), albo dostępnego z zewnątrz identyfikatora transakcji, którego można używać niezależnie od połączenia.

W tym ostatnim przypadku otwierasz transakcję za pomocą TxID, a następnie ponownie łączysz się przy użyciu tego identyfikatora. DBMS utrzymuje blokady i pozwala wybrać sesję z powrotem poprzez TxID. Tak działają transakcje rozproszone z wykorzystaniem protokołów zatwierdzania dwufazowego (takich jak Transakcje XA lub COM + ).

ConcernedOfTunbridgeWells
źródło
148
Optymistyczne blokowanie niekoniecznie używa numeru wersji. Inne strategie obejmują użycie (a) znacznika czasu lub (b) całego stanu samego wiersza. Ta ostatnia strategia jest brzydka, ale unika potrzeby stosowania dedykowanej kolumny z wersją, w przypadkach, gdy nie można modyfikować schematu.
Andrew Swan,
2
@geek - Rozproszone protokoły transakcji, takie jak XA, umożliwiają siatkowanie oddzielnego identyfikatora transakcji wokół jednego lub więcej systemów. Ten typ protokołu pozwala na stosowanie blokad poprzez połączenia w puli, ponieważ identyfikator transakcji jest oddzielany od sesji i podawany jawnie. Powoduje to jednak pewne koszty ogólne i jest podatny na blokadę wycieków i identyfikatory transakcji, jeśli aplikacja nie skrupulatnie je śledzi. Jest to rozwiązanie o wiele cięższe.
ConcernedOfTunbridgeWells
22
@ supercat - Nie zgadzaj się, że optymistyczne blokowanie jest mniej niż 100% dokładne - dopóki sprawdza wszystkie rekordy wejściowe pod kątem transakcji, które powinny pozostać niezmodyfikowane przez cały czas, jest tak dokładne jak blokowanie pesymistyczne (wybierz styl aktualizacji) na tych te same rekordy. Główną różnicą jest to, że optymistyczne blokowanie powoduje obciążenie tylko w przypadku konfliktu, podczas gdy blokowanie pesymistyczne zmniejsza obciążenie ogólne w przypadku konfliktu. Tak optymistyczny jest najlepszy w przypadku, gdy większość transakcji nie powoduje konfliktów - co mam nadzieję, że zwykle dzieje się tak w przypadku większości aplikacji.
RichVel,
2
@Legends - Korzystanie z blokowania optymitycznego byłoby z pewnością odpowiednią strategią dla aplikacji internetowej.
ConcernedOfTunbridgeWells
2
Powinieneś wspomnieć, że wybór zależy również od stosunku odczytu do zapisu: jeśli twoja aplikacja jest głównie aplikacją tylko do odczytu przez wielu użytkowników, a czasami piszesz dane, to przejdź do optymistycznego blokowania. Na przykład StackOverflow ma wiele osób czytających strony, a czasem ktoś je edytuje: w pesymistycznym blokowaniu, kto dostanie blokadę? pierwszy? W optymistycznym blokowaniu osoba, która chce edytować stronę, może to zrobić, o ile ma jej ostatnią wersję.
jehon
177

Blokowanie optymistyczne jest stosowane, gdy nie spodziewasz się wielu kolizji. Wykonanie normalnej operacji kosztuje mniej, ale jeśli zdarzy się kolizja, zapłacisz wyższą cenę za jej rozwiązanie, gdy transakcja zostanie przerwana.

Blokowanie pesymistyczne jest stosowane, gdy przewiduje się kolizję. Transakcje, które naruszałyby synchronizację, są po prostu blokowane.

Aby wybrać odpowiedni mechanizm blokujący, musisz oszacować ilość odczytów i zapisów oraz odpowiednio zaplanować.

Ilya Kochetov
źródło
W normalnym przypadku stwierdzenie jest idealne, ale w szczególnych przypadkach, w których można zarządzać operacją CAS , dopuszczając niedokładność, jak wspomniano w odpowiedzi na @skaffman, powiedziałbym, że to naprawdę zależy.
Hearen
75

Optymistycznie zakłada, że ​​podczas czytania nic się nie zmieni.

Pesymizm zakłada, że ​​coś się stanie i dlatego to blokuje.

Jeśli dane nie są idealnie odczytywane, użyj optymizmu. Możesz dostać dziwny „brudny” odczyt - ale znacznie mniej prawdopodobne jest, że doprowadzi to do impasu i tym podobnych.

Większość aplikacji internetowych jest w porządku z brudnymi odczytami - w rzadkich przypadkach dane nie zgadzają się dokładnie przy następnym przeładowaniu.

Do dokładnych operacji na danych (jak w wielu transakcjach finansowych) używaj pesymizmu. Ważne jest, aby dane były dokładnie odczytywane, bez żadnych niewyświetlanych zmian - dodatkowy koszt blokowania jest tego wart.

Aha, a Microsoft SQL Server domyślnie blokuje strony - w zasadzie wiersz, który czytasz i kilka po obu stronach. Blokowanie wierszy jest dokładniejsze, ale znacznie wolniejsze. Często warto ustawić transakcje na zatwierdzone do odczytu lub bez blokady, aby uniknąć zakleszczeń podczas czytania.

Keith
źródło
Blokowanie optymistyczne JPA pozwala zagwarantować spójność odczytu.
Gili
4
Spójność odczytu to osobna kwestia - dzięki PostgreSQL, Oracle i wielu innym bazom danych masz spójny widok danych, niezależnie od jakichkolwiek aktualizacji, które nie zostały jeszcze zatwierdzone, i nie mają na nie wpływu nawet wyjątkowe blokady wierszy.
RichVel
Muszę się zgodzić z @RichVel. Z jednej strony widzę, jak pesymistyczne blokowanie może zapobiegać nieczytelnym odczytom, jeśli poziom izolacji transakcji jest ODCZYTYWANY NIEPOPRAWIONO. Ale mylące jest twierdzenie, że optymistyczne blokowanie jest podatne na brudne odczyty, nie wspominając o tym, że większość baz danych (w tym najwyraźniej MS SQL Server) ma domyślny poziom izolacji „READ COMMITTED”, który zapobiega nieczytelnym odczytom i sprawia, że ​​optymistyczne blokowanie jest równie dokładne jak pesymistyczny.
antinome
Eric Brower mówi, że bankierzy, w przeciwieństwie do innych, wolą brudne operacje. Twój guru wydaje się absolutnie nie mieć wózków.
Little Alien,
1
Eric Brewer jest guru, który wypowiedział twierdzenie CAP o spójności w bankowości . Jest przeciwnie do tego, za co go honoruje.
Little Alien,
50

Oprócz tego, co już powiedziano:

  • Należy powiedzieć, że optimisticblokowanie ma tendencję do poprawy współbieżności kosztem przewidywalności.
  • Pessimisticblokowanie ma tendencję do zmniejszania współbieżności, ale jest bardziej przewidywalne. Płacisz pieniądze itp.
skaffman
źródło
3
Nie rozumiem, w jaki sposób poprawia się przewidywalność (niezależnie od tego, jak ją definiujesz) dzięki pesymistycznemu blokowaniu - jeśli masz na myśli, że „transakcja może zostać zakończona po przejęciu blokad”, masz rację, ale dopóki transakcja nie będzie miała wszystkich wymaganych blokad, uzyskanie opóźnienia może być opóźnione pozostałe blokady i mogą zostać przerwane z powodu detekcji impasu DB + logiki rozwiązywania. Aplikacje korzystające z pesymistycznego blokowania mogą mieć bardzo nieprzewidywalne czasy wykonania - klasyczny przykład jest taki, że ktoś blokuje rekord X, a następnie idzie na lunch, a następnie użytkownik blokuje rekord X i Y, a następnie kolejne Y i Z i tak dalej, dopóki większość użytkowników nie zostanie zablokowana. ..
RichVel
40

W przypadku konfliktów masz dwie opcje:

  • Możesz spróbować uniknąć konfliktu i właśnie to robi Blokowanie Pesymistyczne.
  • Możesz też zezwolić na wystąpienie konfliktu, ale musisz go wykryć po zatwierdzeniu transakcji i tak właśnie działa Optymistyczne Blokowanie.

Teraz rozważmy następującą anomalię utraconej aktualizacji :

Utracona aktualizacja

Anomalia utraconej aktualizacji może wystąpić na poziomie izolacji Read Committed .

Na powyższym schemacie możemy zobaczyć, że Alice wierzy, że może wypłacić 40, accountale nie zdaje sobie sprawy, że Bob właśnie zmienił saldo konta, a teraz na koncie pozostało tylko 20.

Blokowanie pesymistyczne

Blokowanie pesymistyczne osiąga ten cel, biorąc na koncie blokadę współdzieloną lub blokadę odczytu, dzięki czemu Bob nie może zmienić konta.

Utracona aktualizacja Pesymistyczne blokowanie

Na powyższym schemacie zarówno Alice, jak i Bob uzyskają blokadę odczytu w accountwierszu tabeli, którą przeczytali obaj użytkownicy. Baza danych nabywa te blokady na SQL Server, gdy używa się powtarzalnego odczytu lub szeregowego.

Ponieważ zarówno Alice, jak i Bob odczytali accountwartość PK 1, żaden z nich nie może jej zmienić, dopóki jeden użytkownik nie zwolni blokady odczytu. Wynika to z faktu, że operacja zapisu wymaga akwizycji blokad zapisu / wyłączności, a blokady współdzielone / odczytu zapobiegają blokowaniu zapisu / wyłączności.

Dopiero po zatwierdzeniu transakcji przez Alicję i zwolnieniu blokady odczytu w accountwierszu, Bob UPDATEwznowi i zastosuje zmianę. Dopóki Alice nie zwolni blokady odczytu, UPDATE Boba blokuje.

Aby uzyskać więcej informacji o tym, w jaki sposób ramy dostępu do danych korzystają z pesymistycznej obsługi blokowania baz danych, zobacz ten artykuł .

Optymistyczne blokowanie

Optymistyczne blokowanie pozwala na wystąpienie konfliktu, ale wykrywa go po zastosowaniu AKTUALIZACJI Alicji po zmianie wersji.

Transakcje na poziomie aplikacji

Tym razem mamy dodatkową versionkolumnę. versionKolumna jest zwiększany za każdym razem, aktualizacji lub usuwania jest wykonywana, a to jest również wykorzystywane w klauzuli WHERE w UPDATE i DELETE. Aby to zadziałało, musimy wydać WYBIERZ i odczytać prąd versionprzed wykonaniem UPDATE lub DELETE, ponieważ w przeciwnym razie nie wiedzielibyśmy, jaką wartość wersji przekazać do klauzuli WHERE lub zwiększyć.

Aby uzyskać więcej informacji o tym, jak struktury dostępu do danych implementują optymistyczne blokowanie, zapoznaj się z tym artykułem .

Transakcje na poziomie aplikacji

Systemy relacyjnych baz danych pojawiły się pod koniec lat 70. na początku lat 80., gdy klient zazwyczaj łączył się z komputerem mainframe za pośrednictwem terminala. Dlatego wciąż widzimy, że systemy baz danych definiują terminy, takie jak ustawienie SESSION.

Obecnie przez Internet nie wykonujemy już operacji odczytu i zapisu w kontekście tej samej transakcji z bazą danych, a ACID nie jest już wystarczający.

Rozważmy na przykład następujący przypadek użycia:

wprowadź opis zdjęcia tutaj

Bez optymistycznego blokowania nie ma szans na złapanie tej Utraconej aktualizacji, nawet jeśli transakcje bazy danych wykorzystywałyby Serializable. Wynika to z tego, że odczyty i zapisy są wykonywane w osobnych żądaniach HTTP, a więc w różnych transakcjach w bazie danych.

Tak więc optymistyczne blokowanie może pomóc w zapobieganiu Utraconym aktualizacjom nawet podczas korzystania z transakcji na poziomie aplikacji, które uwzględniają również czas myślenia użytkownika.

Więcej informacji na temat transakcji na poziomie aplikacji lub transakcji logicznych można znaleźć w tym artykule .

Wniosek

Blokowanie optymistyczne jest bardzo przydatną techniką i działa dobrze nawet przy użyciu mniej rygorystycznych poziomów izolacji, takich jak odczyt zatwierdzony lub gdy odczyty i zapisy są wykonywane w kolejnych transakcjach bazy danych.

Wadą optymistycznego blokowania jest to, że ramy dostępu do danych będą wyzwalane po złapaniu OptimisticLockException , a zatem utracie całej pracy, którą wykonaliśmy poprzednio przez aktualnie wykonywaną transakcję.

Im więcej sporów, tym więcej konfliktów i większa szansa na przerwanie transakcji. Wycofanie może być kosztowne dla systemu bazy danych, ponieważ musi on cofnąć wszystkie bieżące oczekujące zmiany, które mogą obejmować zarówno wiersze tabeli, jak i rekordy indeksu.

Z tego powodu pesymistyczne blokowanie może być odpowiednie w przypadku częstych konfliktów, ponieważ zmniejsza ryzyko wycofania transakcji.

Vlad Mihalcea
źródło
W jakich scenariuszach sugerujesz wybranie OptimisticLocking i PessimisticLocking? Czy to zależy od tego, jak często występuje wyjątek OptimisticLockException?
Stimpson Cat
1
To zależy od przypadku użycia. Czasami optymistyczne blokowanie jest jedynym rozwiązaniem (np. Transakcje z wieloma żądaniami). Innym razem blokowanie pesymistyczne jest jedynym rozwiązaniem (np. Blokady doradcze PostgreSQL ). Czasami musisz je połączyć, tak jak w przypadku PESSIMISTIC_FORCE_INCREMENT.
Vlad Mihalcea
22

Pomyślałbym o jeszcze jednym przypadku, w którym pesymistyczne zamknięcie byłoby lepszym wyborem.

Aby uzyskać optymistyczne blokowanie, każdy uczestnik modyfikacji danych musi wyrazić zgodę na stosowanie tego rodzaju blokowania. Ale jeśli ktoś zmodyfikuje dane bez dbania o kolumnę wersji, zepsuje to cały pomysł optymistycznego blokowania.

Nikolay
źródło
Ludzie, którzy próbują użyć optymistycznego i pesymistycznego zamka, mogą też na siebie nawzajem stanąć. Wyobraź sobie scenariusz, w którym sesja optymistyczna odczytuje rekord i wykonuje pewne obliczenia, podczas gdy sesja pesymistyczna aktualizuje rekord, a następnie sesja optymistyczna powraca i aktualizuje ten sam rekord bez odnotowywania wprowadzonych zmian. Wybierz ... dla aktualizacji działa tylko wtedy, gdy każda sesja używa tej samej składni.
lusional
Dobre wyjaśnienie,
oddajcie
15

Istnieją w zasadzie dwie najpopularniejsze odpowiedzi. Pierwsza w zasadzie mówi

Optimistic potrzebuje trójwarstwowej architektury, w której niekoniecznie utrzymuje się połączenie z bazą danych dla sesji, natomiast blokowanie pesymistyczne ma miejsce, gdy blokujesz rekord na wyłączny użytek, dopóki go nie skończysz. Ma znacznie lepszą integralność niż optymistyczne blokowanie, potrzebujesz albo bezpośredniego połączenia z bazą danych.

Inną odpowiedzią jest

optymistyczne (wersjonowanie) jest szybsze z powodu braku blokowania, ale blokowanie (pesymistyczne) działa lepiej, gdy rywalizacja jest wysoka i lepiej jest zapobiegać pracy niż ją odrzucić i zacząć od nowa.

lub

Optymistyczne blokowanie działa najlepiej, gdy masz rzadkie kolizje

Jak to jest umieszczone na tej stronie.

Stworzyłem swoją odpowiedź, aby wyjaśnić, w jaki sposób „zachowaj połączenie” odnosi się do „niskich kolizji”.

Aby zrozumieć, która strategia jest dla Ciebie najlepsza, nie myśl o transakcjach na sekundę, które ma Twój DB, ale o czasie trwania pojedynczej transakcji. Zwykle otwierasz transakcję, wykonujesz operację i zamykasz transakcję. Jest to krótka, klasyczna transakcja, o której pomyślała ANSI, i dobrze jest uciec od blokady. Ale jak wdrożyć system rezerwacji biletów, w którym wielu klientów rezerwuje te same pokoje / miejsca w tym samym czasie?

Przeglądasz oferty, wypełniasz formularz z wieloma dostępnymi opcjami i aktualnymi cenami. Zajmuje to dużo czasu, a opcje mogą stać się nieaktualne, wszystkie niepoprawne ceny między tobą zaczęły wypełniać formularz i nacisnąć przycisk „Zgadzam się”, ponieważ nie było blokady danych, do których masz dostęp, i ktoś inny, bardziej zwinny, interferował zmieniając wszystkie ceny i musisz zacząć od nowa z nowymi cenami.

Zamiast tego możesz zablokować wszystkie opcje podczas ich czytania. To jest scenariusz pesymistyczny. Widzisz, dlaczego to jest do bani. Twój system może zostać zniszczony przez jednego klauna, który po prostu rozpoczyna rezerwację i pali papierosy. Nikt nie może nic zarezerwować, dopóki nie skończy. Twoje przepływy pieniężne spadają do zera. Dlatego w rzeczywistości wykorzystywane są optymistyczne rezerwacje. Ci, którzy zbyt długo marudzą, muszą wznowić rezerwację po wyższych cenach.

W tym optymistycznym podejściu musisz zapisać wszystkie dane, które czytasz (jak w moim powtórnym czytaniu ) i dojść do punktu zatwierdzenia z twoją wersją danych (chcę kupić akcje po cenie wyświetlonej w tym cenniku, a nie bieżącej cenie ). W tym momencie tworzona jest transakcja ANSI, która blokuje DB, sprawdza, czy nic się nie zmienia i zatwierdza / przerywa operację. IMO, jest to skuteczna emulacja MVCC , która jest również powiązana z Optimistic CC i zakłada również, że twoja transakcja uruchomi się ponownie w przypadku przerwania, to znaczy, że dokonasz nowej rezerwacji. Transakcja dotyczy tutaj decyzji użytkownika.

Daleki jestem od zrozumienia, jak ręcznie wdrożyć MVCC, ale myślę, że długoterminowe transakcje z opcją ponownego uruchomienia są kluczem do zrozumienia tematu. Popraw mnie, jeśli gdziekolwiek się mylę. Moja odpowiedź była motywowana tym rozdziałem Alexa Kuznecowa .

Little Alien
źródło
12

W większości przypadków optymistyczne blokowanie jest bardziej wydajne i oferuje wyższą wydajność. Wybierając między blokowaniem pesymistycznym a optymistycznym, weź pod uwagę następujące kwestie:

  • Blokowanie pesymistyczne jest przydatne, jeśli istnieje wiele aktualizacji i stosunkowo duże szanse, że użytkownicy spróbują zaktualizować dane w tym samym czasie. Na przykład, jeśli każda operacja może aktualizować dużą liczbę rekordów jednocześnie (bank może dodawać zyski odsetkowe do każdego konta na koniec każdego miesiąca), a dwie aplikacje uruchamiają takie operacje w tym samym czasie, będą miały konflikty .

  • Blokowanie pesymistyczne jest również bardziej odpowiednie w aplikacjach, które zawierają często aktualizowane tabele. W przypadku tak zwanych punktów aktywnych konflikty są tak prawdopodobne, że optymistyczne blokowanie marnuje wysiłek w wycofywaniu sprzecznych transakcji.

  • Optymistyczne blokowanie jest przydatne, gdy prawdopodobieństwo wystąpienia konfliktów jest bardzo niskie - istnieje wiele rekordów, ale stosunkowo niewielu użytkowników lub bardzo mało aktualizacji i głównie operacje typu do odczytu.

Koenigsegg
źródło
3

Jednym z przypadków użycia optymistycznego blokowania jest użycie aplikacji przez bazę danych, aby umożliwić jednemu z twoich wątków / hostów „zajęcie” zadania. Jest to technika, która regularnie mi się przydaje.

Najlepszym przykładem, jaki mogę wymyślić, jest kolejka zadań zaimplementowana przy użyciu bazy danych, przy czym wiele wątków jednocześnie wykonuje zadania. Jeśli zadanie ma status „Dostępne”, „Zgłoszone”, „Ukończone”, zapytanie bazy danych może powiedzieć coś w rodzaju „Ustaw status =„ Zgłoszony ”gdzie status =„ Dostępny ”. Jeśli wiele wątków próbuje zmienić status w ten sposób, wszystko oprócz pierwszego wątku zawiedzie z powodu brudnych danych.

Zauważ, że jest to przypadek użycia obejmujący tylko optymistyczne blokowanie. Alternatywnie do powiedzenia „Optymistyczne blokowanie jest stosowane, gdy nie spodziewasz się wielu kolizji”, może być również stosowane tam, gdzie oczekujesz kolizji, ale chcesz, aby dokładnie jedna transakcja zakończyła się powodzeniem.

Charlie Camp
źródło
3

Wiele dobrych rzeczy zostało powiedzianych powyżej o optymistycznym i pesymistycznym blokowaniu. Ważną kwestią do rozważenia jest:

Korzystając z optymistycznego blokowania, musimy zachować ostrożność, ponieważ w jaki sposób aplikacja będzie mogła odzyskać te błędy.

Szczególnie w przypadku architektur opartych na komunikatach asynchronicznych może to prowadzić do przetwarzania komunikatów poza kolejnością lub utraty aktualizacji.

Scenariusze awarii należy przemyśleć.

Abhishek Shinde
źródło