SQL Academy · Lekcja

Zakleszczenia: wykrywanie i unikanie

Rozumieć, jak powstają zakleszczenia, jak wykrywa je Postgres oraz projektować reguły kolejności blokad, które im zapobiegają

Lekcja 3 z 414 kroki

Zakleszczenia: wykrywanie i unikanie to bezpłatna lekcja SQL Academy na CoddyKit. To lekcja 3 z 4. Możesz przeczytać całą lekcję poniżej za darmo — a potem ćwiczyć ją interaktywnie w przeglądarce z wbudowanym edytorem kodu i tutorem AI dostępnym 24/7. To część ścieżki edukacyjnej SQL Academy, a Twój postęp synchronizuje się między webem a aplikacją CoddyKit. Kurs SQL Academy zawiera 4 lekcji w sumie.

Czym jest zakleszczenie?

Dwie transakcje posiadają blokady, których potrzebuje druga z nich — żadna nie może kontynuować. Baza danych wykrywa cykl i przerywa jedną z transakcji.

Klasyczne zakleszczenie

Transakcja A blokuje wiersz 1, a transakcja B blokuje wiersz 2. A żąda wiersza 2, a B żąda wiersza 1. Obie pozostają zablokowane.

-- Tx A:
BEGIN;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
-- waiting for B...

-- Tx B:
BEGIN;
UPDATE accounts SET balance = balance - 50 WHERE id = 2;
UPDATE accounts SET balance = balance + 50 WHERE id = 1;
-- waiting for A...

-- ERROR: deadlock detected

PostgreSQL wykrywa zakleszczenia

Co każde deadlock_timeout (domyślnie 1 sekunda) PostgreSQL sprawdza cykle blokad. Jeśli je znajdzie, przerywa jedną transakcję z kodem błędu 40P01.

ERROR:  deadlock detected
DETAIL:  Process 1234 waits for ShareLock on transaction 5678 ...

Zasada kolejności blokad

Rozwiązanie: zawsze uzyskuj blokady w tej samej kolejności we wszystkich ścieżkach kodu.

-- Always update the lower id first:
UPDATE accounts SET balance = balance - 100 WHERE id = LEAST(:from, :to);
UPDATE accounts SET balance = balance + 100 WHERE id = GREATEST(:from, :to);

Zakleszczenia na gorących wierszach

Częste aktualizacje tych samych gorących wierszy zwykle powodują oczekiwanie na blokadę, a nie zakleszczenia. Należy użyć kolejkowania, podzielić gorący wiersz albo serializować aktualizacje w kodzie aplikacji.

FOR UPDATE blokuje odczytywane wiersze

Uzyskuj blokady zapisu już podczas odczytu, aby uniknąć późniejszych niespodzianek:

BEGIN;
SELECT * FROM accounts WHERE id IN (1, 2) ORDER BY id FOR UPDATE;
-- both rows locked in id order
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;

Pomijanie zablokowanych wierszy

W przypadku tabel kolejek można użyć wzorca „pobierz dowolny dostępny wiersz”:

SELECT * FROM jobs
WHERE status = 'pending'
ORDER BY created_at
LIMIT 1
FOR UPDATE SKIP LOCKED;
-- skips rows other workers have locked

NOWAIT

Kończ działanie natychmiast zamiast czekać:

SELECT * FROM accounts WHERE id = 1 FOR UPDATE NOWAIT;
-- ERROR: could not obtain lock on row in relation "accounts"

Diagnozowanie zakleszczeń

Zwiększ wartość log_lock_waits i rejestruj kontekst zakleszczenia w logu. Wpis w logu pokazuje obie transakcje i ich zapytania.

Pętla ponawiania w aplikacji

Zakleszczenia można obsłużyć — ponów przerwaną transakcję:

for (let attempt = 0; attempt < 3; attempt++) {
  try {
    await runTransaction();
    break;
  } catch (e) {
    if (e.code === '40P01') continue;     // deadlock
    throw e;
  }
}

Ograniczanie zakresu blokad

Skracaj transakcje — każdy dotknięty wiersz pozostaje zablokowany aż do COMMIT. Nie wykonuj wywołań HTTP ani długich obliczeń wewnątrz transakcji.

Indeksuj klucze obce, aby uniknąć eskalacji blokad

Podczas usuwania elementu nadrzędnego sprawdzany jest każdy wiersz podrzędny. Bez indeksu FK oznacza to pełne skanowanie tabeli ORAZ blokady wierszy. Indeksuj każdą kolumnę FK.

Podsumowanie

Zakleszczenia się zdarzają — należy projektować system tak, aby je ograniczać.

  • Uzyskuj blokady w spójnej kolejności
  • Używaj FOR UPDATE odpowiednio wcześnie, aby zadeklarować zamiar
  • Używaj SKIP LOCKED w kolejkach
  • Ponawiaj próby po błędach zakleszczenia (40P01)
  • Utrzymuj krótkie transakcje

Szybkie sprawdzenie

Jaka zasada projektowa jest najbardziej niezawodnym sposobem zapobiegania zakleszczeniom?

Bezpłatny start

Ucz się SQL dzięki korepetycjom AI — za darmo

Pisz i uruchamiaj kod w przeglądarce, otrzymuj natychmiastową pomoc od korepetytora AI dostępnego 24/7 i kontynuuj naukę w sieci lub w aplikacji.

Kursy
46
Lekcje
183

Często zadawane pytania

Czy lekcja „Zakleszczenia: wykrywanie i unikanie” jest bezpłatna?

Tak — pełny tekst „Zakleszczenia: wykrywanie i unikanie” jest dostępny za darmo tutaj w sieci. Aby ćwiczyć ją interaktywnie (wbudowany edytor kodu i tutor AI dostępny 24/7) i odblokować resztę kursu SQL Academy, przejdź na CoddyKit PRO. Kurs SQL Academy zawiera 4 lekcji w sumie.

Co nauczysz się w „Zakleszczenia: wykrywanie i unikanie”?

Rozumieć, jak powstają zakleszczenia, jak wykrywa je Postgres oraz projektować reguły kolejności blokad, które im zapobiegają Ćwiczysz SQL Academy z praktycznym kodem, który uruchamiasz bezpośrednio w przeglądarce, a tutor AI dostępny 24/7 odpowiada na Twoje pytania podczas pracy nad lekcją.

Czy potrzebuję doświadczenia, aby zacząć SQL Academy?

Nie wymagamy żadnego doświadczenia. SQL Academy w CoddyKit jest strukturyzowany dla początkujących i zaawansowanych użytkowników, więc możesz zacząć tutaj lub od początku i uczyć się w swoim tempie. To lekcja 3 z 4.

Ile czasu zajmuje lekcja „Zakleszczenia: wykrywanie i unikanie”?

Większość lekcji CoddyKit trwa około 5–10 minut. Każda lekcja to mały, interaktywny krok, dzięki czemu robisz systematyczne postępy i zawsze wracasz dokładnie do tego samego miejsca — na webie i w aplikacji.

Czy mogę pisać i uruchamiać kod w tej lekcji SQL Academy?

Tak. Każda lekcja SQL Academy zawiera wbudowany edytor kodu, więc piszesz i uruchamiasz prawdziwy kod bezpośrednio w przeglądarce i od razu otrzymujesz sprzężenie zwrotne od AI — bez konfiguracji na komputerze.

Wszystkie lekcje w tym kursie

  1. Właściwości ACID i anomalie
  2. Poziomy izolacji: READ COMMITTED, REPEATABLE READ, SERIALIZABLE
  3. Zakleszczenia: wykrywanie i unikanie
  4. Blokowanie optymistyczne a pesymistyczne
← Powrót do SQL Academy