Żeby wszystkie zmiany w twojej bazie danych były pod kontrolą i wykonywały się poprawnie, PostgreSQL używa pojęcia transakcji. To grupa operacji SQL, które wykonują się jako jedna całość. Jeśli coś pójdzie nie tak, zmiany trzeba cofnąć. Właśnie wtedy wchodzą do gry komendy BEGIN, COMMIT i ROLLBACK.
Komendy transakcji nie są tylko dla porządku — mają kluczowe znaczenie dla ochrony danych przed błędami i awariami. Gdy wykonujesz serię operacji SQL, ważne jest, żeby mieć pewność, że wszystko pójdzie dobrze: jeśli jedna komenda nie przejdzie, baza powinna wrócić do stanu początkowego. To jedna z głównych przyczyn, dla których w ogóle są komendy transakcji — pomagają zachować spójność danych.
Poza tym transakcje zapewniają tzw. atomowość: albo wszystkie zmiany są zastosowane razem, albo żadna. Dzięki temu nie ma sytuacji, że baza jest zaktualizowana „do połowy” — np. kasa zeszła z konta, a towar nie został dodany do zamówienia.
No i oczywiście transakcje dają elastyczność. Możesz budować złożone łańcuchy akcji, kontrolować, kiedy je zatwierdzić COMMIT albo cofnąć ROLLBACK, a nawet robić punktowe cofnięcia przez SAVEPOINT. To wszystko sprawia, że praca z bazą jest nie tylko bezpieczna, ale i pod kontrolą.
Komenda BEGIN
Komenda BEGIN mówi PostgreSQL, że zaczynasz transakcję. Po jej wykonaniu wszystkie zmiany, które robisz, są „zawieszone” do momentu, aż zakończysz transakcję przez COMMIT albo cofniesz zmiany przez ROLLBACK.
Klasyczny przykład: załóżmy, że chcesz przelać 100 jednostek waluty z jednego konta na drugie. Zaczynasz transakcję od BEGIN:
BEGIN;
-- Zaczęliśmy transakcję
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
-- Zmniejszyliśmy saldo na koncie 1
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
-- Zwiększyliśmy saldo na koncie 2
Dopóki wykonujesz komendy w ramach transakcji, inni użytkownicy bazy nie zobaczą twoich zmian. Staną się widoczne dopiero po COMMIT.
Komenda COMMIT
Komenda COMMIT kończy transakcję i zapisuje wszystkie zmiany zrobione w jej ramach do bazy danych. Po tej komendzie zmiany są widoczne dla wszystkich użytkowników.
Przykład zakończenia transakcji:
COMMIT;
-- Wszystkie zmiany w transakcji zapisane
Teraz zmiany salda, które zrobiliśmy w powyższym przykładzie, stały się „trwałe”. Kasa została przelana.
Komenda ROLLBACK
Jeśli podczas wykonywania transakcji zauważysz błąd albo zdecydujesz się cofnąć zmiany, możesz użyć komendy ROLLBACK. Ona cofa wszystkie operacje wykonane po komendzie BEGIN.
Załóżmy, że podczas przelewu kasy odkrywasz, że na koncie nie ma wystarczających środków. Wtedy transakcja jest cofana:
BEGIN;
-- Zaczęliśmy transakcję
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
-- Ups, błąd: niewystarczające środki.
ROLLBACK;
-- Wszystkie zmiany cofnięte, baza wróciła do stanu początkowego
Po komendzie ROLLBACK żadne zmiany w bazie nie są zapisane. To mega wygodne, żeby zapobiegać błędom.
Pełny przykład: przelew kasy między kontami
Zbierzmy wszystko razem. Oto pełny przykład transakcji — ze sprawdzeniem salda, przelewem kasy i możliwością cofnięcia w razie błędu:
BEGIN;
-- Zaczynamy transakcję
-- Sprawdzamy saldo na koncie
SELECT balance INTO current_balance FROM accounts WHERE account_id = 1;
-- Sprawdzamy, czy środków wystarczy
IF current_balance >= 100 THEN
-- Jeśli środków wystarczy, robimy przelew
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
UPDATE accounts SET balance = balance + 100 WHERE account_id = 2;
COMMIT;
-- Potwierdzamy zmiany
ELSE
-- Jeśli środków za mało, cofamy transakcję
ROLLBACK;
END IF;
Ten przykład pokazuje, jak komendy transakcji współpracują, żeby zapobiegać niespójności danych.
IF THEN ELSE END IF — to operacje procedur składowanych, które rozkminimy za kilka poziomów:P
Szczegół: ustawienie autocommit
W PostgreSQL domyślnie jest włączony tryb autocommit, więc jeśli wykonujesz komendy poza wyraźną transakcją, są one od razu zapisywane w bazie. Na przykład:
UPDATE accounts SET balance = balance - 100 WHERE account_id = 1;
-- Zmiany od razu zapisane, nawet bez COMMIT
Jeśli chcesz samemu zarządzać transakcjami, zawsze używaj BEGIN do jawnego rozpoczęcia transakcji.
Możesz wyłączyć autocommit dla bieżącej sesji komendą:
SET AUTOCOMMIT TO OFF;
Pamiętaj: jeśli autocommit jest wyłączony, musisz kończyć każdą sesję komendą COMMIT albo ROLLBACK.
Typowe błędy przy pracy z transakcjami
Zapomniany COMMIT. Jeśli zapomnisz zrobić COMMIT, twoje zmiany zostaną niezakończone i przepadną po zakończeniu sesji.
Blokady. Dopóki transakcja nie jest zakończona, zasoby, które używa, mogą być zablokowane. To może prowadzić do problemów z równoczesnym dostępem do danych.
Zbyt częsty ROLLBACK. Czasem programiści są zbyt ostrożni i cofają transakcję bez potrzeby. To prowadzi do powtórnych obliczeń i zwiększa obciążenie bazy.
Zawieszone transakcje. Jeśli zaczniesz transakcję, ale zapomnisz ją zakończyć (ani COMMIT, ani ROLLBACK), może to prowadzić do zawieszenia sesji i blokady zasobów bazy.
Zastosowanie w praktyce
Na rozmowach o pracę na stanowisko developera albo DBA (admina bazy danych) mogą cię zapytać o implementację transakcji w PostgreSQL. Znajomość komend BEGIN, COMMIT i ROLLBACK pokazuje, że umiesz pracować z danymi bezpiecznie i efektywnie.
W praktyce transakcje są szczególnie przydatne do budowania niezawodnych systemów, np. do obsługi zamówień w sklepach internetowych albo naliczania punktów w programach lojalnościowych.
Teraz, gdy ogarniasz podstawowe komendy transakcji, możemy iść dalej i zagłębić się w takie ciekawe tematy jak użycie SAVEPOINT i praca z poziomami izolacji. PostgreSQL — to bezdenne morze możliwości, więc trzymaj się mocno.
GO TO FULL VERSION