Dlaczego to zapytanie powoduje zakleszczenie?
UPDATE TOP(1) system_Queue SET
[StatusID] = 2,
@ID = InternalID
WHERE InternalID IN (
SELECT TOP 1
InternalID FROM system_Queue
WHERE IsOutGoing = @IsOutGoing AND StatusID = 1
ORDER BY MessageID ASC, InternalID ASC)
Dodano wykres zakleszczenia:
<keylock hobtid="72057594236436480" dbid="9" objectname="Z.dbo.system_Queue" indexname="PK_system_Queue" id="lock5b25cc80" mode="X" associatedObjectId="72057594236436480">
<owner-list>
<owner id="processc6fe40" mode="X"/>
</owner-list>
<waiter-list>
<waiter id="processc7b8e8" mode="S" requestType="wait"/>
</waiter-list>
</keylock>
<keylock hobtid="72057594405453824" dbid="9" objectname="Z.dbo.system_Queue" indexname="IX_system_Queue_DirectionByStatus" id="lock48cf3180" mode="S" associatedObjectId="72057594405453824">
<owner-list>
<owner id="processc7b8e8" mode="S"/>
</owner-list>
<waiter-list>
<waiter id="processc6fe40" mode="X" requestType="wait"/>
</waiter-list>
</keylock>
DODANY:
Dziękujemy Sankarowi za artykuł, który zawiera rozwiązania, jak uniknąć tego typu impasu:
- wyeliminuj niepotrzebne kolumny z projekcji czytelnika, aby nie musiał szukać indeksu klastrowego
- dodaj wymagane kolumny jako zawarte kolumny do indeksu nieklastrowanego, aby indeks obejmował się ponownie, aby czytelnik nie sprawdził indeksu klastrowanego
- unikaj aktualizacji, które muszą utrzymywać indeks nieklastrowany
sql-server-2008
deadlock
garik
źródło
źródło
Odpowiedzi:
Wydaje mi się, że próbujesz wykonać SELECT i UPDATE w tej samej instrukcji i na tej samej tabeli.
SELECT utrzymuje wspólną blokadę wartości w indeksie IX_system_Queue_DirectionByStatus, a UPDATE potrzebuje zwolnienia tych blokad, zanim będzie w stanie uzyskać blokadę wyłączną, która zaktualizuje klucz podstawowy (który, jak sądzę, jest klastrowany, a także część IX_system_Queue_DirectionByStatus wartość klucza).
W każdym razie, przypuszczam, że to zapytanie powiedzie się tylko przy rzadkiej szansie, że wybrane i zaktualizowane wartości indeksu nie powodują konfliktu. Czy blokuje się przy każdym wykonaniu (zakładam, że tak będzie).
Oto link, który bardziej szczegółowo wyjaśnia zakleszczenia: http://sqlblog.com/blogs/jonathan_kehayias/archive/2008/07/30/the-anatomy-of-a-deadlock.aspx
źródło
Nie oczekuję, że oznaczysz ten post jako odpowiedź, ale udostępnisz tutaj więcej informacji przez innych ekspertów SQL Server na ten temat.
http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx
http://rusanu.com/2009/05/16/readwrite-deadlock/
źródło