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.