SQL Academy · leksjon

Deadlocks: Oppdaging og forebygging

Forstå hvordan deadlocker oppstår, hvordan Postgres oppdager dem, og utform regler for låserekkefølge som hindrer dem.

Leksjon 3 av 414 trinn

Deadlocks: Oppdaging og forebygging er en gratis leksjon i SQL Academy på CoddyKit. Dette er leksjon 3 av 4. Du kan lese hele leksjonen gratis nedenfor – og deretter øve praktisk i nettleseren med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i SQL Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i SQL Academy inneholder totalt 4 leksjoner.

Hva er en deadlock?

To transaksjoner holder hver sin lås som den andre ønsker — ingen av dem kan fortsette. Databasen oppdager syklusen og avbryter én av transaksjonene.

En klassisk deadlock

Tx A låser rad 1, og Tx B låser rad 2. A ber om rad 2, og B ber om rad 1. Fastlåst.

-- 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 oppdager deadlocks

Ved hvert deadlock_timeout (standard er 1 sekund) kontrollerer PostgreSQL om det finnes låsesykluser. Hvis en syklus oppdages, avbrytes én transaksjon med feilkode 40P01.

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

Regel for låserekkefølge

Løsningen: Hent alltid låser i samme rekkefølge i alle kodebaner.

-- 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);

Deadlocks på belastede rader

Raske oppdateringer av de samme belastede radene utløser ofte låseventing, ikke deadlocks. Bruk køer, partisjoner den belastede raden, eller serialiser oppdateringer i applikasjonskoden.

FOR UPDATE låser rader ved lesing

Skaff skrivelåser ved lesing for å unngå overraskelser senere:

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;

Hopp over låste rader

For køtabeller, mønsteret «hent en valgfri tilgjengelig rad»:

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

NOWAIT

Feil umiddelbart i stedet for å vente:

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

Diagnostisere deadlocks

Øk log_lock_waits og ta med deadlock-konteksten i loggen. Loggoppføringen viser begge transaksjonene og spørringene deres.

Løkke for nye forsøk i applikasjonen

Deadlocks kan håndteres — prøv den avbrutte transaksjonen på nytt:

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

Reduser låseomfanget

Forkort transaksjonene — alle berørte rader forblir låst til COMMIT. Ikke utfør HTTP-kall eller langvarige beregninger i en transaksjon.

Indekser fremmednøkler for å unngå låseeskalering

Når du sletter en overordnet rad, kontrolleres hver underordnede rad. Uten en FK-indeks innebærer dette et fullstendig tabellskann OG radlåser. Indekser hver FK-kolonne.

Oppsummering

Deadlocks oppstår — utform systemet slik at de minimeres.

  • Hent låser i en konsekvent rekkefølge
  • Bruk FOR UPDATE tidlig for å uttrykke intensjon
  • SKIP LOCKED for køer
  • Prøv på nytt ved deadlock-feil (40P01)
  • Hold transaksjonene korte

Hurtigsjekk

Hva er det mest pålitelige designprinsippet for å forhindre deadlocks?

Gratis å komme i gang

Lær deg SQL med en AI-veileder – gratis

Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.

Kurs
46
Leksjoner
183

Ofte stilte spørsmål

Er leksjonen «Deadlocks: Oppdaging og forebygging» gratis?

Ja – hele teksten i «Deadlocks: Oppdaging og forebygging» er gratis å lese her på nettet. For å øve interaktivt med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt, og for å låse opp resten av SQL Academy-kurset, kan du oppgradere til CoddyKit PRO. Kurset i SQL Academy inneholder totalt 4 leksjoner.

Hva lærer jeg i «Deadlocks: Oppdaging og forebygging»?

Forstå hvordan deadlocker oppstår, hvordan Postgres oppdager dem, og utform regler for låserekkefølge som hindrer dem. Du øver på SQL Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.

Trenger jeg erfaring for å begynne med SQL Academy?

Ingen tidligere erfaring er nødvendig. SQL Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.

Hvor lang tid tar leksjonen «Deadlocks: Oppdaging og forebygging»?

De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.

Kan jeg skrive og kjøre kode i denne SQL Academy-leksjonen?

Ja. Alle SQL Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.

Alle leksjonene i dette kurset

  1. ACID-egenskaper og anomalier
  2. Isolasjonsnivåer: READ COMMITTED, REPEATABLE READ, SERIALIZABLE
  3. Deadlocks: Oppdaging og forebygging
  4. Optimistisk kontra pessimistisk låsing
← Tilbake til SQL Academy