Nie widzę żadnego wyraźnego zakresu transakcji w twoim kodzie, więc nie wiem, jakie blokady są już na miejscu podczas aktualizacji; również nie jest jasne, jakiego poziomu izolacji używasz. Ale najczęstszym scenariuszem w tego typu sytuacji jest to, że wcześniej w tej samej transakcji wystawiłeś (blokadę odczytu) na te same wiersze, które próbujesz później zaktualizować. Spowoduje to eskalację blokady i może spowodować zakleszczenie, jeśli dwie transakcje próbują zrobić to samo:
- Transakcja A:wybierz z blokadą odczytu
- Transakcja B:wybierz z readlockiem
- Transakcja A:aktualizacja - chce eskalować blokadę odczytu do blokady zapisu, ale musi czekać, aż transakcja B zwolni blokadę odczytu
- Transakcja B:aktualizacja - chce eskalować blokadę odczytu do blokady zapisu, ale musi czekać, aż transakcja A zwolni blokadę odczytu.
Bingo! zakleszczenie, ponieważ zarówno A, jak i B czekają na siebie, aby zwolnić istniejące blokady odczytu, zanim będą mogli wykonać aktualizację.
Aby temu zapobiec, potrzebujesz podpowiedzi w wyborze, np.
select * from table with (updlock) where blah blah
Zapewni to, że twój wybór użyje blokady zapisu zamiast blokady odczytu, co zapobiegnie eskalacji blokady między równoczesnymi transakcjami.