Dit eksempel i dit spørgsmål viser, at rækkefølgen af låsning afhænger af adgangsmetoden. Denne adgangssti bestemmes ikke direkte af ORDER BY-klausulen i forespørgslen, der er mange faktorer, der kan påvirke denne adgangssti. Derfor kan du ikke forhindre en dødvande blot ved at tilføje en ORDER BY, fordi du stadig kan have to adskilte adgangsstier. Faktisk kunne jeg ved at køre din testcase med ordren ved at ændre sessionsparametrene få to sessioner til at køre ind i en ORA-60 med den samme forespørgsel.
Hvis de involverede sessioner ikke har nogen anden afventende lås, låses rækkerne i samme rækkefølge i alle sessioner vil forhindre dødvande, men hvordan kan du pålideligt fremtvinge denne ordre? Bemærk, at dette kun ville forhindre dette meget specielle tilfælde af dødvande alligevel. Du kan stadig få deadlocks med flere forespørgsler i hver session eller forskellige planer.
I praksis er denne sag virkelig speciel og burde alligevel ikke ske ofte:Hvis du er bekymret for dødvande, tror jeg stadig, der er nemmere metoder til at forhindre dem.
Den nemmeste måde at forhindre dødvande på er at bruge enten FOR UPDATE NOWAIT
eller FOR UPDATE WAIT X
(selvom WAIT X stadig kan udløse en deadlock med værdier på X, der er bedre end deadlock-detektionsmekanismen, tror jeg i øjeblikket 3 sekunder fra 11g -- tak @APC
for rettelsen).
Med andre ord bør begge transaktioner spørge:Giv mig disse rækker og lås dem, men hvis en anden bruger allerede har en lås, returner en fejl i stedet for at vente på ubestemt tid. Det er den ubestemte ventetid, der forårsager dødvande.
I praksis vil jeg sige, at de fleste applikationer med rigtige brugere hellere vil modtage en fejl med det samme end at få en transaktion til at vente på ubestemt tid på, at en anden transaktion afsluttes. Jeg ville overveje FOR UPDATE
uden NOWAIT
kun til ikke-kritiske batchjobs.