CodeGym /Kursy /SQL SELF /Poziom izolacji READ COMMITTED

Poziom izolacji READ COMMITTED

SQL SELF
Poziom 40, Lekcja 0
Dostępny

Sprawdźmy, co robi poziom izolacji READ COMMITTED. Sama nazwa sugeruje, że wszystko, co czytamy w ramach transakcji, jest już "zakomitowane" przez inne transakcje. Trochę jak w życiu, kiedy wierzymy tylko w te plotki, które zostały oficjalnie zapisane w protokole.

Na poważnie, ten poziom gwarantuje, że transakcja nie zobaczy zmian wprowadzonych przez inne transakcje, które nie zostały jeszcze zatwierdzone. To rozwiązuje problem znany jako "brudny odczyt" (Dirty Read). Ale pamiętaj, że dane, które czytasz, mogą się zmienić, jeśli inna transakcja zdąży zrobić commit pomiędzy twoimi zapytaniami. To tworzy ryzyko wystąpienia "niepowtarzalnego odczytu" (Non-Repeatable Read).

W PostgreSQL poziom izolacji READ COMMITTED jest ustawiony domyślnie. To taki tryb domyślny — nie musisz nic specjalnie konfigurować, żeby z niego korzystać.

Przykład użycia poziomu izolacji READ COMMITTED

Zobaczmy, jak to działa w praktyce. Wyobraź sobie, że mamy tabelę accounts, która zawiera informacje o użytkownikach i ich saldach:

CREATE TABLE accounts (
    account_id SERIAL PRIMARY KEY,
    account_name TEXT NOT NULL,
    balance NUMERIC(10, 2) NOT NULL
);

INSERT INTO accounts (account_name, balance)
VALUES ('Alice', 1000.00), ('Bob', 500.00);

Teraz wyobraź sobie następującą sytuację. Sesja 1 i Sesja 2 — dwóch bohaterów naszej historii, obaj pracują z tabelą accounts. Oto co się dzieje:

Sesja 1:

BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE account_name = 'Alice';
-- Żadnego COMMIT ani ROLLBACK na razie.

W tym momencie z balance Alice tymczasowo odjęto 100 jednostek, ale wynik nie został jeszcze zatwierdzony.

Sesja 2:

SET TRANSACTION ISOLATION LEVEL READ COMMITTED;

BEGIN;
SELECT balance FROM accounts WHERE account_name = 'Alice';

Wynik: Sesja 2 widzi saldo Alice jako 1000.00, ponieważ transakcja Sesji 1 jeszcze się nie zakończyła (COMMIT nie został wykonany). Poziom READ COMMITTED chroni nas przed "brudnym odczytem".

Sesja 1 kończy transakcję:

COMMIT;

Teraz saldo Alice jest zaktualizowane i w bazie danych zapisane jest 900.00.

Sesja 2 powtarza zapytanie:

SELECT balance FROM accounts WHERE account_name = 'Alice';

Wynik: teraz Sesja 2 widzi zaktualizowane saldo Alice — 900.00. Zwróć uwagę, że wynik różni się od poprzedniego zapytania, które zwracało 1000.00. To jest problem "niepowtarzalnego odczytu".

Kiedy używać READ COMMITTED?

Poziom izolacji READ COMMITTED to balans między wydajnością a spójnością. Ale są sytuacje, gdzie sprawdza się idealnie:

  1. Proste operacje CRUD: kiedy po prostu czytasz lub aktualizujesz dane bez skomplikowanych zależności.

  2. Aktualizacja rekordów: na przykład masowa aktualizacja danych w tabeli, gdzie ważne jest, by od razu widzieć zatwierdzone zmiany.

  3. Obsługa transakcji: systemy płatności, które pozwalają użytkownikom widzieć tylko potwierdzone dane.

Jednak jeśli wykonujesz złożone zapytania analityczne lub pracujesz z dużymi ilościami danych, może warto rozważyć inny poziom izolacji, na przykład REPEATABLE READ.

Zalety i wady poziomu izolacji READ COMMITTED

Poziom izolacji READ COMMITTED to coś w rodzaju złotego środka. Chroni cię przed brudnymi danymi: nie zobaczysz zmian, które inna transakcja zaczęła, ale jeszcze nie skończyła. Czyli nikt nie przeczyta „surowych” informacji, które mogą być zaraz cofnięte.

Ten tryb działa szybciej niż bardziej rygorystyczne poziomy (REPEATABLE READ lub SERIALIZABLE), bo nie wymaga skomplikowanych blokad i dodatkowych sprawdzeń. Jest dość lekki i jednocześnie niezawodny — właśnie dlatego jest używany domyślnie i świetnie nadaje się do większości codziennych zadań.

Chociaż zapobiega brudnemu odczytowi, READ COMMITTED nie chroni przed:

  • "Niepowtarzalnym odczytem" (Non-Repeatable Read): wartość danych może się zmienić, jeśli inna transakcja wprowadzi zmiany pomiędzy zapytaniami.
  • "Odczytem fantomowym" (Phantom Read): inna transakcja może dodać wiersze, które wpłyną na wynik twojego zapytania.

Porady przy pracy z READ COMMITTED

Zawsze kończ transakcje: nie zapominaj używać COMMIT lub ROLLBACK, bo inaczej mogą pojawić się problemy z blokadami.

Upewnij się, że poziom izolacji jest wystarczający: jeśli musisz mieć pewność, że dane nie zmienią się w trakcie trwania transakcji, rozważ REPEATABLE READ.

Używaj indeksowania: to pomoże PostgreSQL szybciej znajdować dane i stosować zmiany.

Przykład: obsługa zamówień

Załóżmy, że mamy tabelę orders, w której przechowywane są dane o zamówieniach:

CREATE TABLE orders (
    order_id SERIAL PRIMARY KEY,
    customer_name TEXT NOT NULL,
    status TEXT NOT NULL DEFAULT 'pending'
);

INSERT INTO orders (customer_name, status)
VALUES ('Alice', 'pending'), ('Bob', 'pending');

Chcemy zaktualizować status zamówień, które są w stanie "pending":

BEGIN;
SELECT * FROM orders WHERE status = 'pending';
UPDATE orders SET status = 'completed' WHERE status = 'pending';
COMMIT;

Jeśli w trakcie działania inna transakcja doda nowe zamówienie ze statusem "pending" i wykona COMMIT, nasza transakcja nie uwzględni tego wiersza, bo został dodany po rozpoczęciu odczytu.

To przykład "odczytu fantomowego". Jeśli chcesz uniknąć takich sytuacji, musisz użyć SERIALIZABLE.

Poziom izolacji READ COMMITTED to domyślny wybór dla większości baz danych, w tym PostgreSQL. Zapewnia ochronę przed brudnymi odczytami, co czyni go dobrym wyborem dla większości standardowych operacji. Jednak w scenariuszach wymagających ścisłej spójności mogą być potrzebne bardziej rygorystyczne poziomy izolacji. Wybór poziomu izolacji powinien zależeć od twoich konkretnych zadań i wymagań dotyczących wydajności.

2
Zadanie
SQL SELF, poziom 40, lekcja 0
Niedostępne
Tworzenie transakcji z poziomem izolacji READ COMMITTED
Tworzenie transakcji z poziomem izolacji READ COMMITTED
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION