Zarządzanie transakcjami Wprowadzenie do systemów baz danych Transakcja Transakcjami nazywamy procedury, które wprowadzają zmiany do bazy danych lub które wyszukują dane Transakcją może być jedna instrukcja lub zbiór instrukcji tworzących pewną logiczną jednostkę pracy O transakcjach mówimy w kontekście współużytkowania danych przez wielu użytkowników i powstawania ewentualnych wzajemnych konfliktów Samo czytanie danych (bez ich modyfikacji) nie powoduje konfliktów Przyczyną powstawania konfliktów są modyfikacje danych w środowisku wielu użytkowników System zarządzania bazą danych powinien rozwiązać potencjalne konflikty powstające przy przetwarzaniu transakcji Wymagania stawiane transakcjom Niepodzielność – albo wszystkie modyfikacje wchodzące w skład transakcji są wykonane albo żadna Spójność – wszystkie transakcje muszą zachować spójność i integralność bazy danych Izolacja – jeśli transakcja modyfikuje dane, to te dane mogą być czasowo niespójne, dlatego muszą być niedostępne dla innych transakcji dopóty, dopóki transakcja nie skończy ich używać Trwałość – gdy transakcja się kończy, to wszystkie zmiany przez nią dokonane muszą zostać w pełni utrwalone – nawet w przypadku awarii sprzętu (ang. ACID – Atomicity, Consistency, Isolation, Durability) Właściwości transakcji Transakcja to jedna modyfikacja lub seria modyfikacji bazy danych traktowana tak jakby była to jedna modyfikacja Jeśli modyfikacje zachodzą, to wszystkie zachodzą w jednej chwili Użytkownicy mogą zobaczyć stan bazy danych przed transakcją lub po jej zakończeniu, ale nigdy w trakcie Przykłady transakcji i zagrożeń Rezerwacja miejsca w samolocie – możliwe dwukrotne sprzedanie tego samego miejsca Zwiększanie pensji 300 pracowników – możliwa awaria sprzętu w trakcie zapisu na dysk Transfer pieniędzy z konta na konto – obie operacje muszą być wykonana albo żadna W trakcie transferu pieniędzy z konta na konto ktoś sprawdza sumę wszystkich kont, i nie może widzieć stanu pośredniego (z jednego konta pieniądze zniknęły, a na drugim się nie pojawiły) Zatwierdzanie transakcji W języku SQL do zatwierdzenia transakcji służy instrukcja COMMIT Do odwołania transakcji służy polecenie ROLLBACK W standardzie języka SQL nie ma instrukcji zaczynającej transakcję SQL Server umożliwia przeprowadzanie transakcji w 3 trybach AutoCommit – każde polecenie SQL stanowi odrębną transakcję Explicit – transakcję trzeba rozpocząć poleceniem BEGIN TRAN[SACTION] i zakończyć poleceniem COMMIT lub ROLLBACK Implicit – transakcja rozpoczyna się automatycznie po wykonaniu 1 polecenia SQL i trzeba ją zakończyć jawnie poleceniem COMMIT lub ROLLBACK PostgreSQL domyślnie pracuje w trybie automatycznego zatwierdzania transakcji Aby jawnie rozpocząć transakcję, należy wydać instrukcję BEGIN Problem utraconej modyfikacji Transakcja 1 Transakcja 2 BEGIN Wartość pola Miejsca Miejsca = 10 Odczyt (Miejsca = 10) BEGIN Miejsca = 10 Miejsca = Miejsca + 1 Odczyt (Miejsca = 10) Miejsca = 10 UPDATE Miejsca = 11 Miejsca = Miejsca + 5 Miejsca = 11 COMMIT UPDATE Miejsca = 15 Miejsca = 15 COMMIT Miejsca = 15 Problem niezatwierdzonej zależności Transakcja 1 Transakcja 2 Wartość pola Miejsca BEGIN Miejsca = 10 Odczyt (Miejsca = 10) Miejsca = 10 Miejsca = Miejsca + 1 Miejsca = 10 UPDATE Miejsca = 11 ROLLBACK BEGIN Miejsca = 11 Odczyt (Miejsca = 11) Miejsca = 11 Miejsca = Miejsca + 5 = 16 Miejsca = 10 UPDATE Miejsca = 16 Miejsca = 16 COMMIT Miejsca = 16 Częściowe rozwiązanie problemu Zapisując nową wartość, w miejsce starej, należy sprawdzić czy stara wartość nie została zmieniona od czasu ostatniego odczytu (wartość ostatniego odczytu należy zapamiętać) UPDATE SET Miejsca = nowa_wartość WHERE Miejsca = poprzednio_odczytana_wartość AND … Jeśli wartość Miejsca uległa zmianie od ostatniego odczytu, to modyfikacja nie zostanie wykonana i otrzymamy komunikat o aktualizacji 0 liczby wierszy Jeśli wartość Miejsca nie uległa zmianie od ostatniego odczytu, to modyfikacja zostanie wykonana i otrzymamy komunikat o aktualizacji 1 wiersza Izolacja transakcji – język SQL W języku SQL określono 4 poziomy izolacji transakcji W celu zdefiniowania poziomów izolacji transakcji określono 3 rodzaje nieprawidłowych odczytów Poziom izolacji transakcji określa dozwolone dla danego poziomu nieprawidłowe odczyty Im wyższy poziom izolacji, tym mniej dopuszczalnych nieprawidłowych odczytów Im wyższy poziom izolacji tym wolniejsza praca systemu zarządzania bazą danych Dopuszczenie nieprawidłowych odczytów przyspiesza pracę systemu zarządzania bazą danych w porównaniu z najwyższym poziomem izolacji - szeregowym Nieprawidłowe odczyty Brudny odczyt (Dirty read): pierwsza transakcja modyfikuje wiersz, a druga go czyta, zanim zmiana została zatwierdzona przez instrukcję COMMIT. Jeśli pierwsza transakcja została anulowana, zmiana nie miała miejsca i druga transakcja przeczytała wiersz, który naprawdę nigdy nie istniał Odczyt bez powtórzeń (Non-repeatable read): pierwsza transakcja czyta wiersz. Druga go usuwa lub modyfikuje i wykonuje COMMIT przed pierwszą. Teraz pierwsza transakcja mogłaby przeczytać ten sam wiersz jeszcze raz i otrzymać inne wyniki Nieprawidłowe odczyty Odczyt widmo (Phantom): pierwsza transakcja odczytuje wiersze spełniające predykat. Druga wstawia wartości (instrukcja INSERT) lub je modyfikuje (instrukcja UPDATE) tak, że one również spełniają predykat. Następne wykonanie tego samego zapytania przez pierwszą transakcję da inne wyniki Poziomy izolacji i dozwolone odczyty Poziom izolacji Brudny odczyt Odczyt bez powtórzeń Odczyt widmo READ UNCOMMITED TAK TAK TAK READ COMMITED NIE TAK TAK REPEATABLE READ NIE NIE TAK SERIALIZABLE NIE NIE NIE Określanie poziomu izolacji SET TRANSACTION ISOLATION LEVEL {READ UNCOMMITED | READ COMMITED | REPEATABLE READ | SERIALIZABLE} READ WRITE | READ ONLY PostgreSQL obsługuje tylko poziomy: READ COMMITED (domyślny) i SERIALIZABLE wybranie innego poziomu izolacji powoduje ustawienie odpowiedniego wyższego poziomu Szeregowy harmonogram transakcji Transakcje są wykonywane kolejno bez przeplatania się operacji między transakcjami Każda transakcja musi się zakończyć zanim zacznie się nowa transakcja Szeregowy harmonogram transakcji gwarantuje, że baza danych nigdy nie znajdzie się w stanie niespójnym Nieszeregowy harmonogram transakcji W środowisku wielu użytkowników wiele transakcji może nie komunikować się ze sobą i być wykonywane równolegle Szeregowalność to określenie takich harmonogramów nieszeregowych, które zachowują się jak szeregowe Harmonogram nieszeregowy jest poprawny, jeśli tworzy taki sam wynik jak pewne wykonanie szeregowe W celu zapewnienia szeregowalności wiele systemów stosuje blokady Przykład Linie lotnicze sprzedają bilety na 100 lotów dziennie, samolotami o średniej liczbie miejsc w samolocie 120 Daje to średnio 12000 biletów dziennie, 500 biletów na godzinę, 8 biletów na minutę Szeregowanie wszystkich transakcji jest niemożliwe z uwagi na czas trwania jednej transakcji, szczególnie, gdy klient długo się zastanawia Szeregowanie wszystkich transakcji jest także zbyteczne, gdyż transakcje sprzedaży biletów na poszczególne loty są wzajemnie niezależnie Szeregowanie transakcji sprzedaży biletów na pojedynczy lot jest w pełni wykonalne – szczególnie, gdy uwzględnimy, że bilety na jeden lot są sprzedawane przez kilka dni Blokady Wiele baz danych implementuje izolację transakcji za pomocą blokad, które ograniczają dostęp do danych, używanych przez transakcję, innym transakcjom Istnieją dwa typy blokad Blokada współdzielona (shared lock), która pozwala innym użytkownikom odczytywać dane, ale nie pozwala na ich aktualizację Blokada wyłączna, która nie zezwala innym transakcjom nawet na czytanie danych Zakleszczenie BEGIN BEGIN UPDATE wiersz 64 (blokada wiersza 64) UPDATE wiersz 68 (blokada wiersza 68) UPDATE wiersz 68 (czekanie na odblokowanie wiersza 68) UPDATE wiersz 64 (czekanie na odblokowanie wiersza 64) Auto-ROLLBACK COMMIT Przebieg wykonywania transakcji Rozpoczęcie – wprowadzenie transakcji do menadżera Rejestracja wstępnych informacji w dzienniku transakcji Sprowadzenie rekordów bazy danych Rejestracja obrazu danych przed transakcją Obliczenie nowych wartości Rejestracja obrazu danych po transakcji Rejestracja zatwierdzenia Zapis nowych rekordów do bazy danych Po przerwaniu działania w dowolnym momencie można odtworzyć stan bazy danych przed lub po transakcji Transakcje rozproszone W rozproszonych bazach danych dane są rozmieszczone na różnych serwerach – tzw. serwerach sprzężonych Komercyjne serwery baz danych obsługują transakcje rozproszone, czyli transakcje obejmujące modyfikacje danych ulokowanych na różnych serwerach MS SQL Server wyposażony jest w usługę MS DTS (Distributed Transaction Coordinator) do kontroli transakcji rozproszonych i gwarantuje spójność wszystkich transakcji na SQL Serverze i serwerach z nim sprzężonych Warunkiem poprawnego wykonania transakcji rozproszonej jest jej zatwierdzenie na wszystkich serwerach