CodeGym /Kursy /SQL SELF /Użycie SAVEPOINT do zarządzania częściowym ...

Użycie SAVEPOINT do zarządzania częściowym cofnięciem w transakcjach

SQL SELF
Poziom 39 , Lekcja 2
Dostępny

Użycie SAVEPOINT do zarządzania częściowym cofnięciem w transakcjach

Wyobraź sobie, że piszesz książkę. Ale wiesz jak jest: nie zawsze wszystko idzie zgodnie z planem. Czasem napiszesz cały rozdział, ale po przeczytaniu widzisz, że piąty paragraf wyszedł tragicznie. Co robisz? Nie wyrzucasz przecież całego rozdziału do kosza, prawda? Zamiast tego poprawiasz tylko te fragmenty, które budzą wątpliwości.

Mniej więcej tak samo działa SAVEPOINT w PostgreSQL. Pozwala ci:

  1. Tworzyć punkty zapisu wewnątrz transakcji — jak zakładki w książce.
  2. Wracać do tych punktów, żeby cofnąć część wykonanych operacji, nie cofając całej transakcji.
  3. Kontynuować pracę z pozostałymi danymi, bez zaczynania wszystkiego od nowa.

Podstawowa składnia SAVEPOINT

Komendy związane z użyciem SAVEPOINT są całkiem proste. Oto ich podstawowy zestaw:

Tworzenie punktu zapisu (SAVEPOINT):

SAVEPOINT savepoint_name;

To trochę tak, jakbyś mówił: "Zapamiętajmy to miejsce, może później będziemy chcieli tu wrócić."

Cofnięcie do utworzonego punktu zapisu (ROLLBACK TO SAVEPOINT):
ROLLBACK TO SAVEPOINT savepoint_name;

Jeśli coś pójdzie nie tak, wracasz do wskazanego SAVEPOINT i anulujesz wszystkie zmiany od momentu jego utworzenia.

Usunięcie punktu zapisu (RELEASE SAVEPOINT):
RELEASE SAVEPOINT savepoint_name;

To zwalnia miejsce, gdzie była "zakładka". Po tym nie możesz już cofnąć się do tego punktu.

Prosty przykład: zakupy w sklepie internetowym

Wyobraźmy sobie, że prowadzimy sklep internetowy. Klient wrzuca do koszyka kilka produktów i chcemy wykonać transakcję, która obejmuje złożenie zamówienia i zmiany w tabeli stanów magazynowych. Jednak jeśli któryś z etapów się nie uda, chcemy cofnąć tylko część transakcji, a nie wszystko.

BEGIN;

-- Krok 1: Zarezerwować produkt "Książka SQL"
UPDATE inventory SET stock = stock - 1 WHERE product_id = 101;

-- Tworzymy punkt zapisu
SAVEPOINT book_reserved;

-- Krok 2: Zarezerwować produkt "Kubek PostgreSQL"
UPDATE inventory SET stock = stock - 1 WHERE product_id = 102;

-- Ups, okazało się, że nie ma kubków na magazynie!
ROLLBACK TO SAVEPOINT book_reserved;

-- Zatwierdzamy zmiany tylko dla książki
COMMIT;

Co się dzieje w tym przykładzie?

  1. Zaczynamy transakcję przez BEGIN.
  2. Po rezerwacji książki tworzymy punkt zapisu book_reserved. To nasz pierwszy "checkpoint".
  3. Próbowaliśmy zarezerwować kubek, ale pojawił się błąd (np. nie było produktu na magazynie).
  4. Cofnęliśmy się do punktu zapisu book_reserved, żeby anulować tylko zmiany związane z kubkiem.
  5. Na końcu zatwierdzamy zmiany dla książki przez COMMIT.

Bardziej złożony przykład: wieloetapowe przetwarzanie danych

Teraz wyobraź sobie, że pracujesz z systemem zarządzania zamówieniami, gdzie trzeba zaktualizować kilka tabel: orders (zamówienia), inventory (stany magazynowe) i billing (wystawione faktury). Jeśli na którymś etapie coś się wysypie, nie chcesz tracić progresu w innych tabelach. Tu właśnie SAVEPOINT ratuje sytuację.

BEGIN;

-- Krok 1: Utworzyć nowe zamówienie
INSERT INTO orders (order_id, customer_id, status) VALUES (1, 123, 'oczekujące');
SAVEPOINT after_order_created;

-- Krok 2: Zaktualizować stan magazynowy
UPDATE inventory SET stock = stock - 2 WHERE product_id = 101;
SAVEPOINT after_stock_updated;

-- Krok 3: Wykonać płatność
INSERT INTO billing (order_id, amount, status) VALUES (1, 100, 'opłacone');

-- Ups, błąd: karta kredytowa odrzucona!
ROLLBACK TO SAVEPOINT after_stock_updated;

-- Wróciliśmy do kroku po aktualizacji stanu, ale zamówienie zostaje ze statusem "oczekujące".
UPDATE orders SET status = 'nieudane' WHERE order_id = 1;

COMMIT;

Zwróć uwagę, jak dzięki SAVEPOINT podzieliliśmy transakcję na logiczne etapy i wróciliśmy do odpowiedniego punktu, zachowując część zmian.

Przydatne tipy przy pracy z SAVEPOINT

  • Używaj sensownych nazw punktów zapisu. W powyższych przykładach after_order_created jest dużo bardziej czytelne niż po prostu step1.
  • Zagnieżdżone punkty zapisu działają spoko: możesz tworzyć SAVEPOINT nawet wewnątrz cofnięcia do innego punktu.
  • Zwalniaj zasoby, usuwając niepotrzebne punkty przez RELEASE SAVEPOINT. To może poprawić wydajność, szczególnie w dużych transakcjach.

Realne scenariusze użycia

Obsługa operacji bankowych: Na przykład, przy przelewie między kilkoma kontami możesz cofnąć się do konkretnego etapu, jeśli któryś z przelewów się nie udał.

Import danych z plików: Jeśli importujesz duży plik CSV, możesz sprawdzać każdy wiersz i cofać tylko błędne dane, zachowując te poprawne.

Masowa aktualizacja rekordów: Jeśli masz skomplikowany SQL-script do aktualizacji tysięcy wierszy, SAVEPOINT pozwala cofnąć się do poprzedniego etapu, jeśli pojawi się błąd w trakcie wykonywania.

Typowe błędy i pułapki

Czasem użycie SAVEPOINT może prowadzić do niespodziewanych efektów, jeśli nie ogarniasz, jak to działa. Na przykład:

  • Jeśli zapomnisz cofnąć się do punktu zapisu albo go usunąć, możesz stworzyć sytuacje, gdzie zasoby są blokowane aż do końca transakcji.
  • SAVEPOINT nie cofnie działań, które miały miejsce przed utworzeniem punktu zapisu. Na przykład, dane zatwierdzone przez COMMIT są już nie do cofnięcia.

Teraz możesz bezpiecznie eksperymentować w transakcjach, tworząc punkty zapisu tam, gdzie trzeba. Przed nami jeszcze więcej SQL-praktyki, więc szykuj się na kolejną porcję przygód.

Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION