En måde at klare deadlocks på er at have en genforsøgsmekanisme, der venter på et tilfældigt interval og forsøger at køre transaktionen igen. Det tilfældige interval er nødvendigt, så de kolliderende transaktioner ikke hele tiden støder ind i hinanden, hvilket forårsager det, der kaldes en live-lås - noget endnu mere ulækkert at fejle. Faktisk vil de fleste komplekse applikationer have brug for en sådan genforsøgsmekanisme før eller siden, når de skal håndtere transaktionsserialiseringsfejl.
Selvfølgelig, hvis du er i stand til at fastslå årsagen til dødvandet, er det normalt meget bedre at fjerne det, ellers vil kom tilbage for at bide dig. I næsten alle tilfælde, selv når deadlock-tilstanden er sjælden, er den lille smule gennemstrømning og kodning overhead for at få låsene i deterministisk rækkefølge eller få mere grovkornede låse det værd for at undgå lejlighedsvis store latens-hit og den pludselige ydeevne cliff ved skalering af samtidighed.
Når du konsekvent får to INSERT-sætninger fastlåst, er det højst sandsynligt et problem med en unik indeksindsættelsesrækkefølge. Prøv for eksempel følgende i to psql-kommandovinduer:
Thread A | Thread B
BEGIN; | BEGIN;
| INSERT uniq=1;
INSERT uniq=2; |
| INSERT uniq=2;
| block waiting for thread A to commit or rollback, to
| see if this is an unique key error.
INSERT uniq=1; |
blocks waiting |
for thread B, |
DEADLOCK |
V
Normalt er den bedste fremgangsmåde til at løse dette at finde ud af de overordnede objekter, der beskytter alle sådanne transaktioner. De fleste applikationer har en eller to primære enheder, såsom brugere eller konti, der er gode kandidater til dette. Så alt hvad du behøver er for hver transaktion at få låsene på den primære enhed, den berører via SELECT ... FOR UPDATE. Eller hvis du rører flere, få låse på dem alle, men i samme rækkefølge hver gang (bestil efter primærnøgle er et godt valg).