UPDATE-Heap-Tabelle -> Deadlocks auf RID

8

Ich richte einen Testfall ein, um ein bestimmtes Deadlock-Szenario zu beweisen, und benötige einen Einblick in die Vorgänge. Ich habe eine Heap-Tabelle, die üblicherweise HeapTable heißt. Diese Tabelle wird durch 2 Transaktionen gleichzeitig aktualisiert.

Transaktion 1:

BEGIN TRAN

UPDATE HeapTable
SET FirstName = 'Dylan'
WHERE FirstName = 'Ovidiu';

WAITFOR DELAY '00:00:15';

UPDATE HeapTable
SET FirstName = 'Bob'
WHERE FirstName = 'Thierry';

ROLLBACK TRANSACTION

Transaktion 2:

BEGIN TRAN

UPDATE HeapTable
SET FirstName = 'Pierre'
WHERE FirstName = 'Michael';

ROLLBACK TRAN

Ich starte zuerst Transaktion 1, dicht gefolgt von Transaktion 2. Wie erwartet beansprucht Transaktion 1 einige exklusive Sperren zusammen mit einigen absichtlichen exklusiven Sperren. Transaktion 2 wird eingehen und eine Aktualisierungssperre für dieselbe RID anfordern:

spid dbid   ObjId       IndId   Type    Resource     Mode   Status
55    5     711673583   0       RID     1:24336:10   X      GRANT
57    5     711673583   0       RID     1:24336:10   U      WAIT

Ich war etwas überrascht, als die zweite Transaktion nach einer Aktualisierungssperre für dieselbe RID fragte, da ich dachte, dass dies auf einen einzelnen Datensatz hinweist und beide Aktualisierungsanweisungen unterschiedliche Daten verarbeiten. Ich hatte stattdessen irgendwie einen Konflikt auf Seitenebene erwartet.

Wenn die zweite Aktualisierung von Transaktion 1 in Transaktion 2 beginnt, wird dies als Deadlock-Opfer angesehen, was zu einem Rollback von Transaktion 2 und dem Abschluss von Transaktion 1 führt.

Kann mir jemand erklären, warum für die zweite Transaktion eine Aktualisierungssperre für dieselbe RID erforderlich ist, obwohl ein anderer Datensatz aktualisiert wird?

Ich weiß, wie man das behebt (zB mit einem Index). Ich suche nicht nach einer Lösung, sondern nach einer Erklärung, warum 2 Updates, die unterschiedliche Datensätze in einem Heap verarbeiten, dieselbe RID sperren möchten. Ich verwende Read Commited Isolation. Die Tabelle enthält keine nicht gruppierten Indizes.

Jens
quelle

Antworten:

18

Ohne einen Index FirstNamemuss SQL Server jede Zeile überprüfen, um festzustellen, ob sie für die qualifiziert ist UPDATE.

UBeim Lesen jeder Zeile ist eine Aktualisierungssperre erforderlich, um ein häufiges Deadlock-Szenario zu verhindern. Es könnte eine gemeinsame SSperre erforderlich sein, die jedoch weiterhin durch die exklusive XSperre der ersten Transaktion blockiert wird .

Paul White 9
quelle