217
7.2 Verrouillage
ELSE 100
END
ROLLBACK
ALTER INDEX PK_Contact_ContactID
ON Person.Contact
SET (ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);
En modifiant les options d’index, vous observerez les différences de verrouillage.
Diminution de la granularité
Vous pourriez parfois avoir besoin d’empêcher l’escalade de verrous, notamment sur
les requêtes de modification qui touchent une grande partie de la table. Vous avez
pour cela deux moyens. Le plus propre est de découper votre requête de modification
en étapes, pour ne toucher qu’une partie de la table à chaque fois. À l’aide de la
requête listée plus haut, vous pouvez voir la différence de verrouillage de ces deux
instructions :
BEGIN TRAN
UPDATE Person.Contact
SET LastName = UPPER(LastName);
UPDATE TOP (1000) Person.Contact
SET LastName = UPPER(LastName);
ROLLBACK
La première pose un verrou exclusif sur la table, et un UPDATE Person.Contact
WITH (ROWLOCK) n’y change rien, car il n’affecte que le plan d’exécution, pas le comportement d’escalade lors de l’exécution même. La seconde, par contre, pose des verrous sur les lignes (chaque clé de l’index clustered. Ainsi, vous pourriez créer une
boucle WHILE de ce type :
DECLARE @incr int, @rowcnt int
SET @incr = 1
SET @rowcnt = 1
WHILE @rowcnt > 0 BEGIN
UPDATE TOP (1000) Person.Contact
SET LastName = UPPER(LastName)
WHERE ContactID >= @incr
SET @rowcnt = @@ROWCOUNT
SET @incr = @incr + 1000
END
Une seconde solution, relevant plus du bricolage, existe. Elle se base sur le fait
qu’un verrou d’intention posé à un niveau de granularité supérieur n’empêche pas les
verrous de granularité inférieure, et prévient bien sûr la pose de verrous incompatibles. Vous pouvez poser un verrou d’intention exclusif sur la table, par exemple de
cette manière :
7.2 Verrouillage
ELSE 100
END
ROLLBACK
ALTER INDEX PK_Contact_ContactID
ON Person.Contact
SET (ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON);
En modifiant les options d’index, vous observerez les différences de verrouillage.
Diminution de la granularité
Vous pourriez parfois avoir besoin d’empêcher l’escalade de verrous, notamment sur
les requêtes de modification qui touchent une grande partie de la table. Vous avez
pour cela deux moyens. Le plus propre est de découper votre requête de modification
en étapes, pour ne toucher qu’une partie de la table à chaque fois. À l’aide de la
requête listée plus haut, vous pouvez voir la différence de verrouillage de ces deux
instructions :
BEGIN TRAN
UPDATE Person.Contact
SET LastName = UPPER(LastName);
UPDATE TOP (1000) Person.Contact
SET LastName = UPPER(LastName);
ROLLBACK
La première pose un verrou exclusif sur la table, et un UPDATE Person.Contact
WITH (ROWLOCK) n’y change rien, car il n’affecte que le plan d’exécution, pas le comportement d’escalade lors de l’exécution même. La seconde, par contre, pose des verrous sur les lignes (chaque clé de l’index clustered. Ainsi, vous pourriez créer une
boucle WHILE de ce type :
DECLARE @incr int, @rowcnt int
SET @incr = 1
SET @rowcnt = 1
WHILE @rowcnt > 0 BEGIN
UPDATE TOP (1000) Person.Contact
SET LastName = UPPER(LastName)
WHERE ContactID >= @incr
SET @rowcnt = @@ROWCOUNT
SET @incr = @incr + 1000
END
Une seconde solution, relevant plus du bricolage, existe. Elle se base sur le fait
qu’un verrou d’intention posé à un niveau de granularité supérieur n’empêche pas les
verrous de granularité inférieure, et prévient bien sûr la pose de verrous incompatibles. Vous pouvez poser un verrou d’intention exclusif sur la table, par exemple de
cette manière :
