POZIOMY IZOLACJI TRANSAKCJI 1. Microsoft SQL Server 2012 (od SQL Server 2005) W systemie SQL Server można wybrać sposób sterowania współbieżnością. Podstawowy sposób to stosowanie blokad. Wykorzystywane są omawiane wcześniej blokady S, X, U, blokady intencjonalne IS, IX, SIX. Są również inne blokady, np. blokady zakresu klucza (stosowane w pewnych przypadkach do realizacji blokowania predykatowego) i blokady schematu (stosowane w celu uniemożliwienia zmiany struktury tabeli w trakcie wykonywania na niej operacji odczytu lub zapisu). SQL Server realizuje poziomy izolacji transakcji w wersji blokowania (locking READ UNCOMMITTED, locking READ COMMITTED, locking REPETEABLE READ, locking SERIALIZABLE). Można włączyć wielowersyjne sterowanie współbieżnością (takie jak w systemie Oracle). Dostępne są wówczas dwa dodatkowe poziomy izolacji transakcji: READ COMMITTED SNAPSHOT (READ CONSISTENCY) oraz SNAPSHOT (anomalny SERIALIZABLE). Sterowanie współbieżnością w oparciu o blokady. Ustawienie na poziomie sesji (działa do zmiany lub zakończenia sesji zamknięcia połączenia). SET TRANSACTION ISOLATION LEVEL level gdzie level = READ UNCOMMITTED READ COMMITTED REPEATABLE READ SERIALIZABLE Domyślnym poziomem izolacji transakcji jest READ COMMITTED. Sterowanie współbieżnością z wielowersyjnością i blokadami do zapisu (jak w Oracle). READ COMMITTED SNAPSHOT nie ma blokad przy odczycie. Transakcja czyta wersje danych zapisane i zatwierdzone przed instrukcją odczytu. SNAPSHOT ISOLATION nie ma blokad przy odczycie. Transakcja czyta wersje danych zapisane i zatwierdzone przed początkiem transakcji. Przy próbie zapisu danych przez transakcję A system sprawdza czy jest inna transakcja B, która zmodyfikowała ten sam element danych i została zatwierdzona w trakcie działania transakcji A. Jeśli taka transakcja (B) została znaleziona, wówczas A jest wycofywana. READ COMMITTED SNAPSHOT w systemie MS SLQ Server 2005/2008 = READ COMMITTED w systemie Oracle. 1
SNAPSHOT ISOLATION w systemie MS SLQ Server 2005/2008 = SERIALIZABLE w systemie Oracle (do wersji Oracle 10gr2 włącznie; w wersji Oracle 11g zmieniono sterowanie współbieżnością w poziomie izolacji SERIALIZABLE). Sposób włączenia READ COMMITTED SNAPSHOT w systemie MS SLQ Server 2005/2008: USE MASTER ALTER DATABASE nazwa_bazy_danych SET READ_COMMITTED_SNAPSHOT ON SET TRANSACTION ISOLATION LEVEL READ COMMMITTED Sposób włączenia SNAPSHOT ISOLATION w systemie MS SLQ Server 2005/2008: USE MASTER ALTER DATABASE nazwa_bazy_danych SET ALLOW_SNAPSHOT_ISOLATION ON SET TRANSACTION ISOLATION LEVEL SNAPSHOT W systemie Microsoft SQL Server niezależnie od ustawienie poziomu izolacji transakcji można zażądać różnych sposobów blokowania w pojedynczej instrukcji SQL, blokowanie może dotyczyć jednej tabeli. Robi się to przez podanie tzw. wskazówki (hint) w instrukcji SQL. Dodatkowe informacje o blokowaniu na poziomie pojedynczych instrukcji SQL można znaleźć w pomocy do systemu SQL Server (Books Online) pod hasłem Table hints. Wybrane fragmenty zamieszczone są w pliku tsql_hints.pdf (zamieszczam również wersję.doc w formacie Word 2003). Dodatkowe informacje o transakcjach w języku Transact SQL (tryb jawny i niejawny, XACT_ABORT, zagnieżdżanie transakcji) wraz z propozycjami ćwiczeń można znaleźć w pliku tsql_transakcje.pdf (zamieszczam również wersję.doc w formacie Word 2003). Sterowanie współbieżnością transakcji w kursorach. Pozycjonowane zmiany: UPDATE WHERE CURRENT OF nazwakursora DELETE FROM Tabela WHERE CURRENT OF nazwakursora Opcje przy otwieraniu kursora: Typ kursora READ_ONLY: nie można wykonywać pozycjonowanych zmian wierszy przez kursor, blokady nie są zakładane. SCROLL LOCKS: jeśli kursor jest otwarty w transakcji jawnej (BEGIN TRAN COMMIT), to są zakładane normalne blokady U update (długotrwałe, do końca transakcji) i blokady kursora (scroll locks), zwalniane w momencie przejścia do innego wiersza. Jeśli jest otwarty poza transakcją, to są zakładane tylko blokady kursora. Blokady typu scroll lock są niezależne od transakcji i są zwalniane przy przejściu do nowego wiersza lub zamknięciu kursora. 2
Przy niewłączonej opcji automatycznego zamykania kursorów na końcu transakcji może się zdarzyć, że blokady są trzymane nadal po zakończeniu transakcji. SET CURSOR_CLOSE_ON_COMMIT ON ALTER DATABASE SET CURSOR_CLOSE_ON_COMMIT OPTIMISTIC (WITH VALUES): przy odczycie wiersza nie są zakładane blokady. Przy próbie zmodyfikowania wiersza następuje sprawdzenie, czy inna transakcja tego nie zrobiła (już po odczycie wiersza przez kursor, ale przed próbą jego zmodyfikowania). Wiersz wczytywany jest jeszcze raz i porównywane są wartości w kolumnach. Jeśli się nie zmieniły, to aktualizacja następuje, jeśli nie, wówczas zgłaszany jest błąd. OPTIMISTIC (WITH ROW VERSIONING): podobnie, ale w tabeli musi być kolumna typu rowversion (w SQL Server 2008, w starszych wersjach SQL Server 2000 i 2005 był to typ timestamp). Wartość w takiej kolumnie jest zawsze automatycznie modyfikowana przy modyfikacji wiersza, nawet jeśli jest to modyfikacja typu pole1 = pole1 (czyli nie ma zmiany wartości). Dodatkowe informacje o blokowaniu i kursorach w języku Transact SQL wraz z propozycjami ćwiczeń można znaleźć w pliku tsql_poziomy_izolacji.pdf. 2. Oracle Ustawienie dla bieżącej sesji: ALTER SESSION SET ISOLATION_LEVEL = READ COMMITTED lub ALTER SESSION SET ISOLATION_LEVEL = SERIALIZABLE Ustawienia poziomu izolacji tylko dla jednej transakcji: SET TRANSACTION ISOLATION_LEVEL READ COMMITTED; SET TRANSACTION ISOLATION_LEVEL SERIALIZABLE; SET TRANSACTION READ ONLY; Domyślnym poziomem izolacji transakcji jest READ COMMITTED. READ COMMITTED nie ma blokad przy odczycie. Są długie blokady do zapisu zakładane na poziomie wierszy. Transakcja czyta wersje danych zapisane i zatwierdzone przed instrukcją odczytu. SERIALIZABLE nie ma blokad przy odczycie. Transakcja czyta wersje danych zapisane i zatwierdzone przed początkiem transakcji. Są długie blokady do zapisu zakładane na poziomie wierszy. Przy próbie zapisu danych przez transakcję A system sprawdza czy jest 3
inna transakcja B, która zmodyfikowała ten sam element danych i została zatwierdzona w trakcie działania transakcji A. Jeśli jest taka transakcja (B), wówczas instrukcja zapisu jest wycofana i jest generowany wyjątek, który można obsłużyć i w obsłudze wyjątku wycofać transakcję. W Oracle do wersji 10gr2 włącznie poziom SERIALIZABLE był równoważny poziomowi SNAPSHOT w systemie Microsoft SQL Server, zatem np. problem skrzywionego zapisu A5B (write skew) był możliwy. Podobnie problem Read- Only transaction anomaly (patrz materiały uzupełniające do wykładu) był możliwy. W wersji Oracle 11g zmieniono sterowanie współbieżnością w poziomie SERIALIZABLE. Skrzywiony zapis nie jest już możliwy. Problem Read- Only transaction anomaly też już nie występuje. Jednak problem P3 może wystąpić (ale A3 nie występuje). Transakcje rozpoczynają się niejawnie pierwszą instrukcją operująca na danych (SELECT, INSERT, UPDATE, DELETE). Transakcję należy zatwierdzić (COMMIT) lub wycofać (ROLLBACK). Przy każdej zatwierdzonej zmianie danych w bloku zapisywany jest tzw. SCN (System Change Number). Poprzednia postać bloku wraz z poprzednią wartością SCN jest umieszczana w tzw. segmencie wycofania. Instrukcjom także przypisywane są unikalne SCN. W poziomie izolacji transakcji READ COMMITTED instrukcja SELECT o pewnym numerze SCN czyta najnowsze bloki (najpóźniej zmodyfikowane) ale o mniejszym numerze SCN. Ilustruje to poniższy rysunek: SELECT (SCN = 10203) 10200 10200 10205 10201 10197 Segmenty wycofania (Rollback segments) 10205 10202 10190 10202 4
W celu zabezpieczenia się przed problemem A5B (Write Skew) w wersjach Oracle do 10gr2 włącznie można zastosować jawne żądanie zablokowania tabeli przez instrukcję LOCK TABLE lub stosując opcję zdania SELECT: SELECT FOR UPDATE. W celu zabezpieczenia się przed problemem P3 należy stosować jawne blokowanie tabel przez instrukcje LOCK TABLE (patrz poniższa tabela). Typy blokad w systemie Oracle (terminologia Oracle): Blokady wierszy, row locks (TX), wyłączne. Oracle blokuje wiersze w trybie wyłącznym (exclusive row lock) przy wykonywaniu instrukcji INSERT, UPADTE, DELETE oraz SELECT FOR UPDATE. Blokady trwają do końca transakcji. Blokady tabel, table locks (TM) Założenie blokady wierszowej powoduje jednocześnie założenie pewnego typu blokady na całą tabelę. Blokady te określane są wspólnym mianem blokady tabelowe, table locks (TM). Niektóre z tych blokad odpowiadają blokadom intencjonalnym w systemie Microsoft SQL Server i mają podobne znaczenie (RS- - IS, RX- - IX, SRX- - SIX). Blokady S, X oraz SRX są zakładane jawnie poleceniem LOCK TABLE (RS i RX też można założyć tym poleceniem). RS i RX zakładane są automatycznie zgodnie z poniższą tabelą. Typy blokad tabelowych: row share (RS), row exclusive (RX), share (S), share row exclusive (SRX), exclusive (X). Typ blokady tabelowej określa jakie blokady tabelowe mogą być założone przez inne transakcje. SQL Statement Mode of Table Lock Lock Modes Permitted? RS RX S SRX X SELECT...FROM table... none Y Y Y Y Y INSERT INTO table... RX Y Y N N N UPDATE table... RX Y* Y* N N N DELETE FROM table... RX Y* Y* N N N SELECT... FROM table FOR UPDATE OF... RS Y* Y* Y* Y* N LOCK TABLE table IN ROW SHARE MODE RS Y Y Y Y N LOCK TABLE table IN ROW EXCLUSIVE MODE RX Y Y N N N LOCK TABLE table IN SHARE MODE S Y N Y N N LOCK TABLE table IN SHARE ROW EXCLUSIVE MODE SRX Y N N N N LOCK TABLE table IN EXCLUSIVE MODE X N N N N N 5
* pod warunkiem, że nie ma wykluczających się blokad wierszowych (na tych samych wierszach). Blokowanie w kursorach. W systemie Oracle jeśli chcemy stosować pozycjonowane zmiany danych z użyciem kursora, należy przy definiowaniu tego kursora użyć opcji FOR UPDATE. Wówczas przy otwarciu kursora na wiersze zakładane są blokady długotrwałe (do końca transakcji). W systemie Oracle nie ma transakcji zagnieżdżonych (nested), są transakcje autonomiczne. Literatura pomocnicza: 1. Microsoft SQL Server Books Online. 2. Dokumentacja Oracle. 6