SQL od podstaw · część 24

Transakcje i podstawy wydajności

Poznaj COMMIT, ROLLBACK, ACID oraz rolę indeksów. Ćwiczenia w prawdziwym SZBD wyjaśniają granice cofania i współbieżności.

Część bazodanowa INF.03

Transakcja łączy zmiany w jedną całość

Dodanie zamówienia i jego pozycji powinno albo zakończyć się w całości, albo nie pozostawić połowy dokumentu. Transakcja obejmuje spójny zestaw operacji. COMMIT zatwierdza zmiany, ROLLBACK wycofuje niezakończoną transakcję. To nie uniwersalne „cofnij” dla dowolnej operacji wykonanej wcześniej.

Początekwybrana sesja→Zmiany + kontrolajedna całość→COMMIT / ROLLBACKzatwierdź / wycofaj
ACIDZnaczenie
Atomicity — atomowośćTransakcja jest traktowana jako całość.
Consistency — spójnośćPoprawna transakcja zachowuje ustalone reguły danych. Sama baza nie odgadnie wszystkich reguł biznesowych.
Isolation — izolacjaOkreśla, jak współbieżne operacje widzą swoje zmiany.
Durability — trwałośćZatwierdzone zmiany są utrwalane zgodnie z gwarancjami i konfiguracją silnika.

Ćwiczenie w rzeczywistym MySQL / MariaDB

Użyj wyłącznie własnej bazy kursowej z tabelami InnoDB. Polecenia wykonaj w tej samej sesji połączenia; w phpMyAdmin możesz wysłać ten pokazowy pakiet razem. Nie umieszczaj pomiędzy nimi CREATE, ALTER, DROP ani TRUNCATE, które mogą spowodować implicit commit.

START TRANSACTION;
UPDATE produkty SET cena = cena + 10 WHERE id = 1;
SELECT id, cena FROM produkty WHERE id = 1;
ROLLBACK;
SELECT id, cena FROM produkty WHERE id = 1;

Dla danych startowych własna sesja zobaczy najpierw 130, a po ROLLBACK ponownie 120. Inna sesja może widzieć dane inaczej zależnie od poziomu izolacji. COMMIT zamiast ROLLBACK pozostawiłby zmianę. Przy autocommit pojedyncze polecenia są zwykle zatwierdzane automatycznie; jawna transakcja zmienia granicę tej jednostki pracy.

To ćwiczenie wymaga prawdziwego SZBD. Edytor w poprzednich lekcjach odrzuca ręczne BEGIN/COMMIT/ROLLBACK. Przy błędzie własnego pakietu przywraca jego stan, a Reset wczytuje dane startowe. Nie symuluje współbieżnych sesji, poziomów izolacji ani trwałości serwera.

Ta sama próba cofnięcia w innych bazach

-- SQL Server: jedna sesja, baza ćwiczeniowa
BEGIN TRANSACTION;
UPDATE produkty SET cena = cena + 10 WHERE id = 1;
SELECT id, cena FROM produkty WHERE id = 1;
ROLLBACK TRANSACTION;
SELECT id, cena FROM produkty WHERE id = 1;

-- Oracle 19c: transakcja DML rozpoczyna się automatycznie
UPDATE produkty SET cena = cena + 10 WHERE id = 1;
SELECT id, cena FROM produkty WHERE id = 1;
ROLLBACK;
SELECT id, cena FROM produkty WHERE id = 1;

W Oracle wyłącz automatyczne zatwierdzanie w używanym kliencie, jeśli jest włączone dla tego ćwiczenia. W Access transakcje obsługuje np. DAO Workspace przez metody BeginTrans, CommitTrans i Rollback; nie wkleja się START TRANSACTION z MySQL do zwykłej kwerendy Access.

' Access VBA / DAO, lokalna baza ćwiczeniowa
Dim ws As DAO.Workspace
Dim db As DAO.Database
Set ws = DBEngine.Workspaces(0)
Set db = CurrentDb
On Error GoTo Blad
ws.BeginTrans
db.Execute "UPDATE produkty SET cena = cena + 10 WHERE id = 1", dbFailOnError
ws.Rollback  ' celowo cofamy próbę
Exit Sub
Blad:
On Error Resume Next
ws.Rollback

Fragment wstaw do procedury Sub w module swojej bazy. Nie uruchamiaj go, gdy ta sama przestrzeń robocza ma inną otwartą transakcję. Obsługa tabel podłączonych do zewnętrznego silnika zależy od sterownika i źródła. Powyższy kod pokazuje kontrolę transakcji lokalnego ACE, nie emulację SQL Server.

Izolacja, blokady i zakleszczenia

Dwie sesje mogą próbować zmienić ten sam rekord. Silnik używa blokad lub wersjonowania; poziom izolacji określa dopuszczalne zjawiska. Brudny odczyt widzi niezatwierdzoną zmianę, niepowtarzalny odczyt — zmianę odczytanego rekordu, a fantom — zmianę zbioru pasujących wierszy. Nazwy poziomów nie oznaczają identycznej implementacji w każdym produkcie.

Trzymaj transakcje krótkie, aktualizuj obiekty w stałej kolejności i nie czekaj w otwartej transakcji na odpowiedź człowieka. Deadlock oznacza cykl oczekiwań; baza może przerwać jedną transakcję. Aplikacja powinna rozpoznać błąd i ewentualnie ponowić całą jednostkę pracy według kontrolowanej reguły, a nie tylko ostatnie UPDATE. Nie traktuj NOLOCK jako uniwersalnego przyspieszenia poprawnego raportu.

Indeks i plan wykonania

Indeks jest dodatkową strukturą pomagającą odnaleźć dane. Może przyspieszyć filtrowanie, złączenie lub sortowanie, ale zajmuje miejsce i kosztuje przy INSERT/UPDATE/DELETE. Nie twórz indeksu na każdej kolumnie. Dobierz go do rzeczywistych zapytań i sprawdź plan.

-- Własna baza kursowa MySQL / MariaDB
CREATE INDEX idx_zamowienia_status_data ON zamowienia(status, data);
EXPLAIN SELECT id, data FROM zamowienia
WHERE status = 'oplacone' AND data >= '2026-02-01';

Plan pokazuje sposób dostępu, możliwe/wybrane indeksy i szacowania. Przy czterech rekordach pełny skan może być racjonalny; mała próbka nie dowodzi przewagi indeksu w produkcji. EXPLAIN ANALYZE w obsługujących go wersjach faktycznie wykonuje zapytanie — odróżniaj go od samego planu szacowanego.

SQL Server udostępnia plany w SSMS; Oracle EXPLAIN PLAN i narzędzia DBMS_XPLAN. W Access analizuj projekt kwerendy i indeksy tabel, nie wklejaj MySQL EXPLAIN. Indeks złożony (status,data) nie jest automatycznie równie użyteczny dla filtra wyłącznie po data. Warunek przedziału dat bywa łatwiejszy do wsparcia indeksem niż YEAR(data)=2026.

Ćwiczenia i rozwiązania

  1. W bazie kursowej wykonaj powyższą próbę ROLLBACK i zanotuj cenę przed, w trakcie i po. Oczekiwane: 120 → 130 → 120.
  2. Wyjaśnij, czemu ROLLBACK po wcześniejszym COMMIT nie przywraca ceny. Zatwierdzenie zakończyło jednostkę pracy; potrzebna byłaby nowa operacja korygująca lub odpowiednie odtworzenie.
  3. Uzasadnij, dlaczego indeks może przyspieszyć SELECT, a spowolnić INSERT. Odczyt korzysta z uporządkowanej struktury, zapis musi ją dodatkowo utrzymać.

Źródła: MySQL — transakcje, MySQL EXPLAIN, Access DAO. Rozszerzenie wspierające INF.03.4: spójność i wydajność. Dalej: użytkownicy, uprawnienia i bezpieczeństwo.

Przewijanie do góry