Ditt exempel i din fråga visar att låsordningen beror på åtkomstmetoden. Denna åtkomstväg bestäms inte direkt av ORDER BY-satsen i frågan, det finns många faktorer som kan påverka denna åtkomstväg. Därför kan du inte förhindra ett dödläge bara genom att lägga till en ORDER BY eftersom du fortfarande kan ha två distinkta åtkomstvägar. Genom att köra ditt testfall med ordern och ändra sessionsparametrarna kunde jag faktiskt få två sessioner att köra in i en ORA-60 med samma fråga.
Om de inblandade sessionerna inte har något annat lås på gång, låser du raderna i samma ordning i alla sessioner kommer att förhindra dödlägen, men hur kan du på ett tillförlitligt sätt tvinga fram denna ordning? Observera att detta bara skulle förhindra detta mycket speciella fall av dödläge ändå. Du kan fortfarande få dödlägen med flera frågor i varje session eller olika planer.
I praktiken är det här fallet verkligen speciellt och borde ändå inte hända ofta:om du är orolig för dödlägen tror jag fortfarande att det finns enklare metoder för att förhindra dem.
Det enklaste sättet att förhindra ett dödläge är att använda antingen FOR UPDATE NOWAIT
eller FOR UPDATE WAIT X
(även om WAIT X fortfarande kan utlösa ett dödläge med värden på X som är överlägsna detekteringsmekanismen för dödläge, för närvarande 3 sekunder från 11g tror jag -- tack @APC
för korrigeringen).
Med andra ord, båda transaktionerna bör fråga:ge mig dessa rader och lås dem, men om en annan användare redan har ett lås returnerar ett fel istället för att vänta på obestämd tid. Det är den obestämda väntan som orsakar låsningar.
I praktiken skulle jag säga att de flesta applikationer med riktiga användare hellre får ett felmeddelande omedelbart än att en transaktion väntar på obestämd tid på att en annan transaktion ska slutföras. Jag skulle överväga FOR UPDATE
utan NOWAIT
endast för icke-kritiska batchjobb.