Zakleszczenia: wykrywanie i unikanie
Rozumieć, jak powstają zakleszczenia, jak wykrywa je Postgres oraz projektować reguły kolejności blokad, które im zapobiegają
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 detectedPostgreSQL 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 lockedNOWAIT
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?
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
- Właściwości ACID i anomalie
- Poziomy izolacji: READ COMMITTED, REPEATABLE READ, SERIALIZABLE
- Zakleszczenia: wykrywanie i unikanie
- Blokowanie optymistyczne a pesymistyczne