W tej lekcji zajmiemy się jednym z najważniejszych aspektów pracy z bazami danych, szczególnie w środowiskach wieloużytkownikowych, czyli transakcjami. Transakcje to mechanizmy, które pozwalają grupować operacje na bazie danych w jedną jednostkę pracy, co umożliwia zarządzanie spójnością i integralnością danych w sytuacjach, gdy zachodzą operacje równoległe, wielokrotne modyfikacje danych lub w przypadku wystąpienia błędów.
Transakcje są niezbędne, gdy wprowadzamy lub modyfikujemy dane w bazie, zwłaszcza w środowiskach produkcyjnych, gdzie wiele operacji na bazie odbywa się jednocześnie. Przyjrzymy się dokładnie, jak działają transakcje, jakie mają właściwości, jak je implementować w SQL, a także jakie problemy mogą wystąpić przy pracy z transakcjami i jak można je rozwiązywać.
Co to jest transakcja?
Transakcja w kontekście baz danych to sekwencja jednej lub więcej operacji SQL (takich jak INSERT, UPDATE, DELETE), które są traktowane jako jedna jednostka pracy. Transakcja musi spełniać tzw. zasady ACID, aby zapewnić, że wszystkie operacje w jej ramach są wykonywane poprawnie, lub nie są wykonywane wcale, jeśli coś pójdzie nie tak. W skrócie:
- A – Atomicity (atomowość): Transakcja jest niepodzielna – albo wszystkie operacje w ramach transakcji zostaną wykonane, albo żadna z nich nie zostanie zatwierdzona.
- C – Consistency (spójność): Transakcja prowadzi bazę danych z jednego spójnego stanu do innego spójnego stanu.
- I – Isolation (izolacja): Każda transakcja jest izolowana od innych i nie wpływa na ich przebieg, dopóki nie zostanie zakończona.
- D – Durability (trwałość): Po zakończeniu transakcji zmiany w danych są trwałe i przetrwają ewentualne awarie systemu.
Jak działają transakcje?
W SQL transakcje zaczynają się w momencie wykonania pierwszej operacji na danych, a kończą się w momencie wykonania polecenia COMMIT (zatwierdzenie transakcji) lub ROLLBACK (wycofanie transakcji). W trakcie trwania transakcji zmiany dokonywane na danych nie są widoczne dla innych transakcji, dopóki nie zostaną zatwierdzone.
Przykładowa sekwencja operacji w transakcji wygląda następująco:
- START TRANSACTION – Rozpoczyna transakcję.
- Wykonanie operacji, np. INSERT, UPDATE, DELETE.
- COMMIT – Zatwierdza wszystkie operacje wykonane w ramach transakcji i zapisuje je na trwałe w bazie danych.
- Alternatywnie, ROLLBACK – Wycofuje wszystkie operacje wykonane w ramach transakcji, przywracając stan sprzed jej rozpoczęcia.
Przykład: Prosta transakcja
Załóżmy, że mamy dwie tabele: Konta i HistoriaTransakcji, które przechowują informacje o kontach użytkowników i ich transakcjach finansowych. Chcemy dokonać przelewu środków z jednego konta na drugie, co wymaga dwóch operacji – odjęcia środków z jednego konta i dodania ich do drugiego. Aby uniknąć sytuacji, w której jedna z tych operacji zostanie wykonana, a druga nie (np. w wyniku błędu), używamy transakcji:
START TRANSACTION; -- Odejmowanie kwoty z konta nadawcy UPDATE Konta SET saldo = saldo - 500 WHERE numer_konta = '123456'; -- Dodawanie kwoty do konta odbiorcy UPDATE Konta SET saldo = saldo + 500 WHERE numer_konta = '654321'; -- Zatwierdzenie transakcji COMMIT;
Jeśli obie operacje zakończą się sukcesem, zmiany zostaną zatwierdzone i zapisane na stałe w bazie danych. W przypadku wystąpienia błędu, np. gdy jedno z kont nie istnieje, możemy wycofać całą transakcję:
ROLLBACK;
W ten sposób mamy pewność, że obie operacje zostaną wykonane poprawnie albo żadna z nich nie zostanie zatwierdzona.
Zasady ACID w praktyce
Transakcje muszą spełniać zasady ACID, które są kluczowe dla zachowania spójności i integralności danych.
- Atomowość: Jeśli w trakcie transakcji wystąpi błąd, wszystkie zmiany zostaną cofnięte. Dzięki temu mamy pewność, że dane nie zostaną zapisane w połowicznie zmienionym stanie.Przykład: W trakcie przelewu środków na konto odbiorcy występuje błąd. Dzięki atomowości transakcji operacja jest całkowicie wycofywana, a stan konta nadawcy nie zmienia się.
- Spójność: Każda transakcja przenosi bazę danych z jednego spójnego stanu do drugiego. W praktyce oznacza to, że baza danych zawsze będzie zgodna z zasadami integralności (np. ograniczenia kluczy obcych, ograniczenia unikalności).
- Izolacja: Transakcje są izolowane od siebie, co oznacza, że operacje w jednej transakcji nie są widoczne dla innych, dopóki transakcja nie zostanie zakończona. Izolacja ma kluczowe znaczenie w środowiskach wieloużytkownikowych, gdzie wiele operacji odbywa się równocześnie.
- Trwałość: Po zatwierdzeniu transakcji (czyli po wykonaniu COMMIT), jej zmiany stają się trwałe. Oznacza to, że nawet w przypadku awarii systemu, te zmiany zostaną zachowane.
Poziomy izolacji transakcji
Jednym z kluczowych aspektów transakcji jest izolacja, która określa, jak transakcje wpływają na siebie nawzajem. SQL definiuje różne poziomy izolacji, które kontrolują, w jakim stopniu jedna transakcja może “widzieć” zmiany wprowadzane przez inne transakcje. Istnieją cztery główne poziomy izolacji:
- Read Uncommitted – Najniższy poziom izolacji. Transakcja może odczytywać dane, które nie zostały jeszcze zatwierdzone przez inne transakcje. Może prowadzić do problemów z “brudnym odczytem” (ang. dirty reads), czyli odczytaniem danych, które mogą zostać wycofane przez inną transakcję.
- Read Committed – Odczyt danych jest dozwolony tylko wtedy, gdy inna transakcja zakończyła się i zatwierdziła zmiany. Ten poziom izolacji zapobiega “brudnym odczytom”, ale nadal mogą wystąpić “niepowtarzalne odczyty” (ang. non-repeatable reads), czyli sytuacje, gdy dane odczytane przez jedną transakcję mogą się zmienić, zanim transakcja zostanie zakończona.
- Repeatable Read – Gwarantuje, że dane odczytane przez jedną transakcję nie zmienią się, dopóki transakcja nie zostanie zakończona. Zapobiega “brudnym odczytom” i “niepowtarzalnym odczytom”, ale nie chroni przed “phantom reads” (czyli sytuacją, w której nowe wiersze zostaną dodane do zestawu danych przez inną transakcję).
- Serializable – Najwyższy poziom izolacji, w którym każda transakcja jest wykonywana tak, jakby była jedyną działającą transakcją w systemie. Zapewnia pełną izolację, ale kosztem wydajności, ponieważ ogranicza równoczesne wykonywanie operacji.
Problemy związane z transakcjami
W pracy z transakcjami mogą wystąpić pewne problemy, szczególnie w środowiskach wieloużytkownikowych. Oto najczęstsze z nich:
- Dirty Read – Transakcja odczytuje dane, które zostały zmodyfikowane przez inną transakcję, ale nie zostały jeszcze zatwierdzone. Jeśli tamta transakcja zostanie wycofana, odczytane dane są nieprawidłowe.
- Non-Repeatable Read – W trakcie jednej transakcji dane, które zostały już odczytane, są zmieniane przez inną transakcję, co prowadzi do niespójnych wyników, gdy próbujemy odczytać te dane ponownie.
- Phantom Read – W trakcie jednej transakcji inna transakcja dodaje nowe wiersze do zestawu danych, co sprawia, że wyniki zapytania są różne przy kolejnych odczytach w tej samej transakcji.
- Deadlock – Zablokowanie, które występuje, gdy dwie lub więcej transakcji wzajemnie czekają na zasoby blokowane przez siebie nawzajem. Aby rozwiązać ten problem, systemy baz danych mają mechanizmy do wykrywania i rozwiązywania zakleszczeń (ang. deadlock detection), które automatycznie wycofują jedną z transakcji, aby przerwać blokadę.
Używanie blokad w transakcjach
Aby zapobiec problemom z jednoczesnym dostępem do tych samych danych przez różne transakcje, systemy bazodanowe stosują blokady (ang. locks). Blokady chronią dane przed równoczesnym modyfikowaniem lub odczytywaniem przez różne transakcje. Istnieją dwa główne rodzaje blokad:
- Blokady wyłączające (exclusive locks) – Używane, gdy transakcja modyfikuje dane. Blokada wyłączająca uniemożliwia innym transakcjom odczytywanie i modyfikowanie tych samych danych, dopóki bieżąca transakcja nie zostanie zakończona.
- Blokady współdzielone (shared locks) – Stosowane, gdy transakcja tylko odczytuje dane. Inne transakcje mogą również odczytywać te dane, ale nie mogą ich modyfikować, dopóki blokada współdzielona nie zostanie zwolniona.
Blokady są automatycznie zarządzane przez system zarządzania bazą danych (DBMS), ale istnieją sytuacje, w których programista musi świadomie manipulować blokadami, aby zapewnić odpowiednią izolację i zapobiec konfliktom między transakcjami.
Podsumowanie
Transakcje to fundamentalny mechanizm w relacyjnych bazach danych, który zapewnia spójność, integralność i izolację danych w środowiskach wieloużytkownikowych. Dzięki zasadom ACID transakcje gwarantują, że operacje na bazach danych są bezpieczne i niezawodne. Izolacja transakcji ma kluczowe znaczenie w środowiskach, w których wiele operacji odbywa się jednocześnie. Umiejętność zarządzania transakcjami, dobierania odpowiedniego poziomu izolacji oraz radzenia sobie z potencjalnymi problemami, takimi jak deadlocki, jest kluczowa dla administratorów i programistów baz danych.
W następnej lekcji omówimy blokady i zarządzanie dostępem do danych w większych, rozproszonych systemach, w tym techniki replikacji i partycjonowania danych, które pozwalają na skalowanie baz danych w celu obsługi większej liczby użytkowników i operacji.
Gratulacje! Ukończyłeś lekcję 12.
Przejdź teraz do lekcji 13 >> Zarządzanie blokadami (Locks) i dostępem do danych
Spis Treści - darmowy kurs SQL
Wprowadzenie: Czym jest baza danych?
Lekcja 1: Instalacja dedykowanego środowiska dla SQL
Lekcja 2: Tworzenie bazy danych
Lekcja 3: Tworzenie tabel w SQL
Lekcja 4: Wstawianie danych do bazy danych SQL
Lekcja 5: Pobieranie danych z bazy danych SQL
Lekcja 6: Aktualizacja i usuwanie danych SQL
Lekcja 7: Operacje na danych (JOIN)
Lekcja 8: Funkcje agregujące i grupowanie danych (GROUP BY)
Lekcja 9: Podzapytania (Subqueries)
Lekcja 10: Indeksy w bazach danych
Lekcja 11: Optymalizacja zapytań SQL
Lekcja 12: Transakcje w bazach danych
Lekcja 13: Zarządzanie blokadami (Locks) i dostępem do danych
Lekcja 14: Replikacja danych w bazach danych
Lekcja 15: Partycjonowanie danych SQL
Lekcja 16: Widoki (Views) w bazach danych
Lekcja 17: Procedury składowane (Stored Procedures) i funkcje w SQL
Lekcja 18: Wyzwalacze (Triggers) w bazach danych
Lekcja 19: Zaawansowane indeksowanie w bazach danych
Lekcja 20: Narzędzia do zarządzania dużymi danymi (Big Data) w SQL
Lekcja 21: Bezpieczeństwo baz danych
Dodatki:
- Spis najważniejszych funkcji SQL