UPDATE heap table -> Deadlocks on RID

8

Je suis en train de mettre en place un cas de test pour prouver un certain scénario de blocage et j'ai besoin d'avoir un aperçu de ce qui se passe. J'ai une table de tas, appelée de manière conventionnelle HeapTable. Ce tableau est mis à jour par 2 transactions simulées.

Transaction 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

Transaction 2:

BEGIN TRAN

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

ROLLBACK TRAN

Je déclenche d'abord la transaction 1, suivie de près par la transaction 2. Comme prévu, la transaction 1 réclamera des verrous exclusifs, ainsi que des verrous exclusifs intentionnels. La transaction 2 entrera et demandera un verrou de mise à jour sur le même RID:

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

J'ai été un peu surpris de voir la deuxième transaction demander un verrou de mise à jour sur le même RID, car je pensais que cela pointait vers un seul enregistrement et que les deux instructions de mise à jour traitaient des données différentes. Je m'attendais en quelque sorte à un conflit au niveau de la page.

Lorsque la deuxième mise à jour de la transaction 1 démarre dans la transaction 2, elle sera considérée comme une victime de blocage entraînant un retour en arrière de la transaction 2 et l'achèvement de la transaction 1.

Quelqu'un peut-il m'expliquer pourquoi la deuxième transaction nécessiterait un verrou de mise à jour sur le même RID bien que la mise à jour d'un enregistrement différent?

Je sais comment résoudre ce problème (par exemple avec un index). Je ne cherche pas de correctif, je cherche en fait une explication pour laquelle 2 mises à jour gérant différents enregistrements dans un tas voudraient verrouiller le même RID. J'utilise l'isolement de lecture engagée. Il n'y a aucun index non cluster sur la table.

Jens
la source

Réponses:

18

Sans index FirstName, SQL Server doit vérifier chaque ligne pour voir si elle remplit les conditions UPDATE.

Il faut un Uverrou de mise à jour lors de la lecture de chaque ligne pour éviter un scénario de blocage commun. Cela pourrait prendre un Sverrou partagé , mais cela serait toujours bloqué par le Xverrou exclusif détenu par la première transaction.

Paul White 9
la source