Współbieżność
Technikum » SBD » SQL » Współbieżność
Współbieżność to zdolność do jednoczesnego realizowania wielu procesów (wątków) opartych na wspólnych danych. Polega ona na przełączaniu między procesami w bardzo krótkich przedziałach czasu, co sprawia wrażenie, że procesy wykonywane są równocześnie. Ten mechanizm znajduje szerokie zastosowanie w serwerach bazodanowych, które muszą obsługiwać jednocześnie wielu użytkowników. Aby każdy z użytkowników mógł pracować tak, jakby był jedynym użytkownikiem bazy danych, konieczne jest odizolowanie operacji (transakcji) wykonywanych przez tych użytkowników.
Kontrola współbieżności
Kontrola współbieżności w serwerach bazodanowych może odbywać się na podstawie:
- modelu optymistycznego
- modelu pesymistycznego
Model optymistyczny
Model optymistyczny opiera się na założeniu, że modyfikowanie i odczytywanie tych samych danych przez różnych użytkowników jest mało prawdopodobne, chociaż nie niemożliwe. W związku z tym można przeprowadzić transakcję bez blokowania zasobów. Jedynie w sytuacji modyfikowania danych zasoby bazy są sprawdzane w celu wykrycia konfliktów.
Model pesymistyczny
Model pesymistyczny zakłada wystąpienie konfliktów, dlatego dane są blokowane za każdym razem, gdy jakaś transakcja próbuje je odczytać lub modyfikować.
Blokowanie danych
Blokowanie danych stosujemy w celu zagwarantowania integralności i spójności danych w trakcie realizowania transakcji. Dzięki temu użytkownicy nie mogą odczytywać danych, które są właśnie zmieniane przez innych użytkowników, oraz nie mogą równocześnie modyfikować tych samych danych. Bez blokad dane znajdujące się w bazie bardzo szybko stałyby się niespójne, a definiowane na nich zapytania dawałyby błędne wyniki.
Serwery bazodanowe automatycznie ustawiają blokady, ale na potrzeby własnej aplikacji można modyfikować ich standardowe ustawienia.
Tryby blokad
Istnieją dwa tryby blokad. Decydują one, czy możliwe jest założenie blokady na dane, które wcześniej zostały zablokowane przez inny proces.
- Blokady współdzielone S (ang. Shared) są zakładane domyślnie na odczytywanych obiektach tylko na czas wykonania zapytania. Jeżeli dane zostały zablokowane w trybie S, to możliwe jest założenie na nie blokady S przez inne procesy.
- Blokady wyłączne X (ang. eXclusive) są zakładane na modyfikowanych obiektach i domyślnie utrzymywane do zakończenia całej transakcji. Użytkownicy modyfikujący dane blokują innych użytkowników.
Zakresy blokad
Blokady mogą być zakładane na różnym poziomie szczegółowości — na poziomie wierszy, kluczy indeksów, stron, tabel, zakresów lub bazy. Dla każdej transakcji dynamicznie jest określany odpowiedni poziom, na którym należy założyć blokadę. Poziomy, na których zakładane są blokady, są ustawiane i kontrolowane przez serwer bazodanowy. To on sprawdza, czy blokady przydzielone na jednym poziomie respektują blokady ustawione na innym poziomie.
Im większe obiekty są blokowane, tym dłużej nie są one dostępne dla użytkownika (mniejsza współbieżność), ale dzięki temu zmniejsza się liczba blokad, którymi musi zarządzać serwer.
Zakleszczenia
Zakleszczenie (ang. Deadlock) powstaje, gdy jeden proces próbuje założyć blokadę powodującą konflikt z blokadą, którą próbuje założyć inny proces. W wyniku nie mogą zostać założone blokady wymagane do ukończenia rozpoczętych procesów. Serwery bazodanowe posiadają algorytmy, które automatycznie wykrywają zakleszczenia i przerywają wykonywanie jednej z transakcji.
Izolowanie transakcji
Wiemy, że transakcja musi być izolowana, czyli próba odczytania danych z tabeli, na której przeprowadzana jest transakcja przez innego użytkownika, zakończy się niepowodzeniem. Dopiero pojawienie się polecenia COMMIT powoduje właściwą modyfikację danych, zdjęcie blokad z danych i umożliwia dostęp do nich innym użytkownikom.
W zależności od istniejącego na serwerze bazodanowym poziomu izolowania transakcji może pojawić się jeden z następujących problemów:
- Utrata aktualizacji (ang. Lost or buried updates) — problem pojawi się, gdy dwie transakcje modyfikują te same dane. Żadna z transakcji nie wie, że druga transakcja korzysta z tych samych danych. W efekcie transakcja, która zakończy się później, zmodyfikuje dane, niszcząc zmiany dokonane przez transakcję, która zakończyła się wcześniej. Domyślnie skonfigurowany serwer nie dopuści do utraty aktualizacji.
- Brudne odczyty (ang. Dirty reads) — problem pojawia się, gdy jedna transakcja dokonuje zmian danych, a druga w tym czasie odczytuje te dane. W efekcie transakcja odczytuje dane, które nie zostały jeszcze zatwierdzone i mogą zostać wycofane. Domyślnie skonfigurowany serwer nie dopuści do brudnych odczytów.
- Niepowtarzalne odczyty (ang. Non-repeatable reads) występują, gdy powtórzenie w ramach transakcji tego samego odczytu daje inny wynik. Może to być spowodowane tym, że po pierwszym odczycie (a nie po zakończeniu transakcji) zostaną zdjęte blokady założone na odczytywane dane. Niezablokowane dane mogą zostać zmienione przez inne działania, a powtórne ich odczytanie da inny wynik. Domyślnie skonfigurowany serwer dopuszcza niepowtarzalne odczyty.
- Odczyty widma (ang. Phantom reads) występują, gdy pomiędzy dwoma odczytami tych samych danych w ramach jednej transakcji zmieni się liczba odczytywanych wierszy (na przykład w wyniku wykonania w międzyczasie instrukcji INSERT lub DELETE na tych danych). Domyślnie skonfigurowany serwer dopuszcza odczyty widma.
Poziomy izolowania transakcji
Blokad używamy w celu zabezpieczenia danych w trakcie współbieżnego wykonywania transakcji. Pozwala to na wykonywanie transakcji w pełnej izolacji od innych transakcji i zapewnia przez cały czas poprawność danych w bazie.
Dzięki temu możliwe jest wykonywanie kilku transakcji w tym samym czasie, tak jakby były wykonywane jedna po drugiej, czyli szeregowo.
Transakcje nie zawsze wymagają pełnej izolacji. Możemy wpływać na sposób zakładania blokad przez serwery bazodanowe, zmieniając poziom izolacji transakcji.
Poziom izolacji określa stopień, do którego dana transakcja musi być izolowana od innych transakcji. Najniższy poziom izolacji to maksymalny stopień współbieżności, ale jest on okupiony najmniejszym stopniem spójności danych. Natomiast wyższy stopień izolacji transakcji zwiększa poprawność danych, ale zmniejsza stopień współbieżności. Najwyższy poziom izolacji gwarantuje najwyższy poziom spójności danych kosztem ograniczenia do minimum współbieżności.
Serwery bazodanowe pozwalają ustawiać na poziomie serwera, baz danych lub pojedynczych sesji poziom izolowania transakcji.
Standard SQL3 definiuje cztery poziomy izolacji transakcji:
- Read Uncommitted,
- Read Committed,
- Repeatable Read,
- Serializable.
Read Uncommitted
Read Uncommitted to tryb niezatwierdzonego odczytu. Jest to najniższy poziom izolacji transakcji. Odczyt danych nie powoduje założenia blokady współdzielonej. Tylko fizycznie uszkodzone dane nie będą odczytywane. Na tym poziomie pojawiają się brudne odczyty, niepowtarzalne odczyty i odczyty widma. Nie występuje jedynie problem z utratą aktualizacji. Ten tryb może być stosowany do odczytywania danych, o których wiemy, że w czasie odczytywania nie będą modyfikowane.
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
Przykład
Read Committed
Read Committed to tryb odczytu zatwierdzonego. Jest to domyślny poziom izolacji stosowany przez MS SQL Server. Podczas odczytu danych zostanie założona na nie blokada współdzielona. Założona blokada eliminuje brudne odczyty. Natomiast nadal występują niepowtarzalne odczyty oraz odczyty widma.
SET TRANSACTION ISOLATION LEVEL READ COMMITTED;
Przykład
Repeatable Read
Repeatable Read to tryb powtarzalnego odczytu. Założona na dane blokada współdzielona jest utrzymywana aż do zakończenia całej transakcji. Dzięki temu, że inny proces nie może zmodyfikować odczytywanych danych, zostały wyeliminowane niepowtarzalne odczyty, natomiast nadal występują odczyty widma.
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ
Przykład
Serializable
Serializable to tryb szeregowania. Transakcje odwołujące się do tych samych danych są szeregowane, czyli wykonywane jedna po drugiej. Jest to najwyższy poziom izolacji transakcji, gdzie transakcje są w pełni izolowane od siebie. Na czas trwania transakcji blokowane są całe obiekty, a nie tylko odczytywane dane, co pozwala wyeliminować odczyty widma, ale powoduje, że inni użytkownicy nie mogą modyfikować przechowywanych w obiekcie danych. Na przykład odczytując jeden wiersz tabeli, blokujemy możliwość modyfikowania danych w całej tabeli.
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
Przykład