Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Pourquoi insérer un bloc d'instructions TSQL lorsque le niveau d'isolement de transaction pour une autre transaction est sérialisable avec un filtre non conflictuel ?

Le premier problème dans votre scénario de test est que la table n'a pas d'index utile sur firstname . La seconde est que la table est vide.

À partir de Verrouillage de plage de clés en BOL

Il n'y a pas d'index approprié pour prendre RangeS-S se verrouille afin de garantir une sémantique sérialisable, SQL Server doit verrouiller toute la table.

Si vous essayez d'ajouter un index clusterisé sur la table sur la colonne du prénom comme ci-dessous et répétez l'expérience...

CREATE CLUSTERED INDEX [IX_FirstName] ON [dbo].[dummy] ([firstname] ASC)

... vous constaterez que vous êtes toujours bloqué !

Malgré le fait qu'un index approprié existe maintenant et que le plan d'exécution montre qu'il est recherché pour satisfaire la requête.

Vous pouvez voir pourquoi en exécutant ce qui suit

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

BEGIN TRAN

SELECT *
FROM   dummy
WHERE  firstname = 'abc'

SELECT resource_type,
       resource_description, 
       request_mode
FROM   sys.dm_tran_locks
WHERE  request_session_id = @@SPID

COMMIT 

Retours

+---------------+----------------------+--------------+
| resource_type | resource_description | request_mode |
+---------------+----------------------+--------------+
| DATABASE      |                      | S            |
| OBJECT        |                      | IS           |
| PAGE          | 1:198                | IS           |
| KEY           | (ffffffffffff)       | RangeS-S     |
+---------------+----------------------+--------------+

SQL Server ne prend pas simplement un verrou de plage sur exactement la plage que vous spécifiez dans votre requête.

Pour un prédicat d'égalité sur un index unique, s'il existe une clé correspondante, il prendra simplement un verrou normal plutôt que n'importe quel type de verrou de plage.

Pour un prédicat de recherche non unique, il supprime les verrous sur toutes les clés correspondantes dans la plage plus la "suivante" à la fin de la plage (ou sur ffffffffffff pour représenter l'infini s'il n'existe pas de clé "suivante"). Même les enregistrements "fantômes" supprimés peut être utilisé dans cette gamme de verrouillage à clé.

Comme décrit ici pour un prédicat d'égalité sur un index unique ou non unique

Donc avec une table vide le SELECT finit toujours par verrouiller l'index entier. Vous devez également avoir préalablement inséré une ligne entre abc et lmn et alors votre insertion réussirait.

insert into dummy values('def', 'def')