Deadlocks: Registrering og forebyggelse
Forstå, hvordan deadlocks opstår, hvordan Postgres registrerer dem, og design regler for låserækkefølge, der forebygger dem.
Deadlocks: Registrering og forebyggelse er en gratis SQL Academy-lektion på CoddyKit. Dette er lektion 3 af 4. Du kan læse hele lektionen gratis nedenfor — og derefter øve dig praktisk i browseren med en indbygget kodeeditor og en AI-vejleder, der er tilgængelig døgnet rundt. Den er en del af læringsforløbet i SQL Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. SQL Academy-kurset indeholder 4 lektioner i alt.
Hvad er en deadlock?
To transaktioner holder hver sin lås, som den anden ønsker — ingen af dem kan fortsætte. Databasen registrerer cyklussen og afbryder den ene transaktion.
En klassisk deadlock
Transaktion A låser række 1, og transaktion B låser række 2. A beder om række 2, og B beder om række 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 detectedPostgreSQL registrerer deadlocks
For hvert deadlock_timeout (standard: 1 sekund) kontrollerer PostgreSQL, om der findes låsecyklusser. Hvis der gør, afbryder den en transaktion med fejlkoden 40P01.
ERROR: deadlock detected
DETAIL: Process 1234 waits for ShareLock on transaction 5678 ...Regel for låserækkefølge
Løsningen er altid at hente låse i samme rækkefølge på tværs af alle kodeveje.
-- 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å meget belastede rækker
Hurtige opdateringer af de samme meget belastede rækker udløser ofte låseventetider, ikke deadlocks. Brug køer, partitionér den belastede række, eller serialisér opdateringer i applikationskoden.
FOR UPDATE låser læste rækker
Hent skrivelåse allerede ved læsningen for at undgå 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;Spring over låste rækker
Til køtabeller er mønsteret "hent en vilkårlig tilgængelig række":
SELECT * FROM jobs
WHERE status = 'pending'
ORDER BY created_at
LIMIT 1
FOR UPDATE SKIP LOCKED;
-- skips rows other workers have lockedNOWAIT
Mislykkes med det samme i stedet for at vente:
SELECT * FROM accounts WHERE id = 1 FOR UPDATE NOWAIT;
-- ERROR: could not obtain lock on row in relation "accounts"Diagnosticering af deadlocks
Øg log_lock_waits, og registrer deadlock-konteksten i loggen. Logposten viser begge transaktioner og deres forespørgsler.
Gentagelsesløkke i applikationen
Deadlocks kan håndteres — gentag den afbrudte transaktion:
for (let attempt = 0; attempt < 3; attempt++) {
try {
await runTransaction();
break;
} catch (e) {
if (e.code === '40P01') continue; // deadlock
throw e;
}
}Reducering af låseomfanget
Forkort transaktionerne — hver række, der berøres, forbliver låst indtil COMMIT. Udfør ikke HTTP-kald eller langvarige beregninger i en transaktion.
Indeksér fremmednøgler for at undgå eskalering af låse
Når du sletter en overordnet række, kontrolleres hver underordnet række. Uden et FK-indeks kræver det en fuld tabelscanning OG rækkelåse. Indeksér hver FK-kolonne.
Opsummering
Deadlocks forekommer — design systemet, så de begrænses.
- Hent låse i en ensartet rækkefølge
- Brug FOR UPDATE tidligt for at erklære hensigten
- Brug SKIP LOCKED til køer
- Gentag ved deadlock-fejl (40P01)
- Hold transaktionerne korte
Hurtigt tjek
Hvad er det mest pålidelige designprincip til at forhindre deadlocks?
Lær SQL med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 46
- Lektioner
- 183
Ofte stillede spørgsmål
Er lektionen “Deadlocks: Registrering og forebyggelse” gratis?
Ja — hele teksten til “Deadlocks: Registrering og forebyggelse” kan læses gratis her på nettet. Hvis du vil øve dig interaktivt med en indbygget kodeeditor og en AI-vejleder døgnet rundt og få adgang til resten af SQL Academy-kurset, skal du opgradere til CoddyKit PRO. SQL Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Deadlocks: Registrering og forebyggelse”?
Forstå, hvordan deadlocks opstår, hvordan Postgres registrerer dem, og design regler for låserækkefølge, der forebygger dem. Du øver dig i SQL Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på SQL Academy?
Der kræves ingen tidligere erfaring. SQL Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 3 af 4.
Hvor lang tid tager lektionen “Deadlocks: Registrering og forebyggelse”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne SQL Academy-lektion?
Ja. Alle SQL Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- ACID-egenskaber og anomalier
- Isolationsniveauer: READ COMMITTED, REPEATABLE READ, SERIALIZABLE
- Deadlocks: Registrering og forebyggelse
- Optimistisk vs. pessimistisk låsning