web-dev-qa-db-fra.com

Verrouillage dans "Lire l'instantané engagé"

Si une mise à jour est exécutée sur une table avec un niveau d'isolation "Lis Snapshot" et un commit est en attente

par exemple:

  1. update table1 set col1 = col1 + 1 where PKcol < 3
  2. update table1 set col1 = col1 + 1 where PKcol = 3
  3. update table1 set col1 = col1 + 1 where NonPKcol < 3
  4. update table1 set col1 = col1 + 1 where NonPKcol = 3
  5. update table1 set col1 = col1 + 1 where PKcol < 3 and NonPKcol = 5

Dans la case ci-dessus, PKCOL est une clé primaire dans le tableau et le non-ckcol est une clé non primaire.

Les mises à jour seront-elles verrouillées pour seules les lignes satisfaisant à la condition "où"? Est-il basé sur la valeur ou l'index ou la colonne primaire?

5
IT researcher

Le comportement exact des modifications simultanées dépend en partie du chemin d'accès choisi par SQL Server pour localiser les enregistrements à modifier.

Si SQL Server utilise l'index en cluster pour localiser les données à modifier, les serrures seront généralement prises sur les touches d'index en cluster (et/ou les pages, etc.). Si SQL Server localise des lignes à modifier à l'aide d'un index non clusterié, les verrous seront effectués sur l'index non clustered. Dans les deux cas, les verrous exclusifs sont également généralement prises sur l'index en cluster avant que la modification ne soit réellement effectuée.

Anticiper le comportement de verrouillage peut être un exercice amusant et éducatif, mais cela souvent la mauvaise question à poser. Si vous rencontrez un blocage de blocage sur des verrous où cela ne semble pas nécessaire, alors cela pourrait est la bonne question, mais c'est un très avancé, nécessitant une version détaillée. connaissances internes pour expliquer complètement. Je montrerai un exemple basé sur vos données plus tard.

Le plus souvent, la vraie question est "quel niveau d'isolement dois-je utiliser?". Les serrures sont un détail de mise en œuvre, utilisé pour fournir les garanties offertes par les différents niveaux d'isolation. Les garanties sont la chose importante. Vous devez comprendre les différents comportements possibles sous chaque niveau d'isolement, puis apportez un choix éclairé. Veuillez vous reporter à ce lien pour tous les détails.

Lors de la modification des données, RCSI se comporte de même que la norme READ COMMITTED. Il bloquera s'il doit lire quelque chose qui est actuellement verrouillé par les modifications non engagées d'une autre session. Une fois la session de blocage commet ou réalise ses modifications, la mise à jour bloquée continue, en lisant les valeurs engagées présentes au moment de la libération du blocage de blocage. Ce comportement est nécessaire pour empêcher les "mises à jour perdues", qui ne sont autorisées sous aucun niveau d'isolation pris en charge par SQL Server.

La démonstration suivante montre que le comportement de blocage précis dépend de laquelle les verrous sont nécessaires en fonction du plan de requête sélectionné par l'optimiseur. Dans certains cas, la mise à jour bloquera, dans d'autres cas, ce n'est pas le cas. SQL Server respecte toujours les garanties fournies par le niveau d'isolation de l'utilisateur, quel que soit le comportement de verrouillage défini par la mise en œuvre.

Table de test et données

CREATE TABLE dbo.Table1
(
    PKcol integer PRIMARY KEY, 
    NonPKCol integer NULL UNIQUE, 
    col1 integer NULL
);

INSERT dbo.Table1
    (PKcol, NonPKCol, col1)
VALUES
    (1,1,0),
    (2,2,0),
    (3,3,0),
    (4,4,0),
    (5,5,0);

Mise à jour non engagée

Sur une connexion séparée, exécutez:

BEGIN TRANSACTION;
UPDATE dbo.Table1 SET NonPKCol = 997 WHERE PKcol = 3;
UPDATE dbo.Table1 SET NonPKCol = 998 WHERE NonPKCol = 3;
UPDATE dbo.Table1 SET NonPKCol = 999 WHERE NonPKCol = 5;

Notez l'absence d'un COMMIT ou ROLLBACK TRANSACTION.

Résultats de test

-- (1) Succeeds (no conflicting locks encountered)
update table1 set col1 = col1 + 1 where PKcol < 3

-- (2) Waits for an X lock for clustered index key PKcol = 3
update table1 set col1 = col1 + 1 where PKcol = 3

-- (3) Waits on U lock for clustered index key PKcol = 3
update table1 set col1 = col1 + 1 where NonPKcol < 3

-- (3) Succeeds when read access is by NONCLUSTERED index
update t set col1 = col1 + 1 from table1 t with(index(2)) where NonPKcol < 3

-- (4) Blocks on U lock for NONCLUSTERED index key NonPKcol = 3
update table1 set col1 = col1 + 1 where NonPKcol = 3

-- (5) Blocks on U lock for nonclustered index key NonPKcol = 5
update table1 set col1 = col1 + 1 where PKcol < 3 and NonPKcol = 5

-- (5) Succeeds when access is by CLUSTERED index
update t set col1 = col1 + 1 from table1 t with(index(1)) where PKcol < 3 and NonPKcol = 5
8
Paul White 9