211
7.2 Verrouillage
même temps les mêmes lignes. Par contre, ils permettent de protéger les opérations
de lecture contre l’écriture simultanée par une autre transaction, ce qui pourrait
déboucher sur des lectures sales. Ils sont incompatibles avec les verrous d’écriture
(X), ce qui permet, dans l’autre sens, de prévenir une lecture sur une ressource en
cours de modification.
Prenons la requête suivante, qui met à jour la table d’en-têtes de commandes
pour ajouter dix jours à la date d’envoi, puis ajoute dans la même transaction dix
jours à la date limite de paiement dans la table de détail de commandes :
BEGIN TRAN
BEGIN TRY
UPDATE Purchasing.PurchaseOrderHeader
SET ShipDate = DATEADD(day, 10, ShipDate)
UPDATE Purchasing.PurchaseOrderDetail
SET DueDate = DATEADD(day, 10, DueDate)
COMMIT TRAN
END TRY
BEGIN CATCH
IF (XACT_STATE()) <> 0
ROLLBACK TRAN
END CATCH
Si une lecture a lieu entre les deux instructions, elle peut trouver des dates de
paiement antérieures aux dates d’envoi, ce qui est une incohérence fonctionnelle.
Pour éviter cela, une lecture ne peut se faire que lorsqu’un verrou S est posé sur les
ressources. Ce verrou étant incompatible avec le verrou X, il doit attendre la libération des verrous X des ressources souhaitées.
Les verrous de type exclusifs (exclusive, X) sont des verrous d’écriture, posés sur
des lignes en cours de modification (INSERT, DELETE, UPDATE). Ils sont incompatibles
avec tout type de verrou, y compris eux-mêmes : quelles que soient les options de la
base ou de la session, il est interdit à deux transactions d’écrire simultanément les
mêmes ressources. Si cela était possible, ce serait le chaos 1 . On ne peut poser ni verrou exclusif, ni verrou partagé, etc., sur une ressource qui possède déjà un verrou
exclusif. On ne peut donc pas non plus lire une ligne en cours de modification, dans
un niveau d’isolation qui pose un verrou partagé à la lecture.
Les verrous de mise à jour (update, U) sont posés dans les niveaux d’isolation qui
maintiennent les verrous partagés toute la durée de la transaction (REPEATABLE READ
et SERIALIZABLE), ils permettent d’éviter une forme courante de verrou mortel (deadlock), lorsque la lecture sert, dans une instruction suivante, aux mises à jour. Dans
ce cas, le verrou partagé doit être converti en verrou exclusif. Mais, si une autre transaction maintient elle aussi des verrous partagés sur ces ressources, la première doit
1. Il existe sur certains SGBDR un niveau d’isolation de la transaction nommé CHAOS, qui permet les écritures simultanées. SQL Server ne le supporte pas. Le niveau d’isolation minimal est
READ UNCOMMITTED, comme nous le verrons plus loin.
7.2 Verrouillage
même temps les mêmes lignes. Par contre, ils permettent de protéger les opérations
de lecture contre l’écriture simultanée par une autre transaction, ce qui pourrait
déboucher sur des lectures sales. Ils sont incompatibles avec les verrous d’écriture
(X), ce qui permet, dans l’autre sens, de prévenir une lecture sur une ressource en
cours de modification.
Prenons la requête suivante, qui met à jour la table d’en-têtes de commandes
pour ajouter dix jours à la date d’envoi, puis ajoute dans la même transaction dix
jours à la date limite de paiement dans la table de détail de commandes :
BEGIN TRAN
BEGIN TRY
UPDATE Purchasing.PurchaseOrderHeader
SET ShipDate = DATEADD(day, 10, ShipDate)
UPDATE Purchasing.PurchaseOrderDetail
SET DueDate = DATEADD(day, 10, DueDate)
COMMIT TRAN
END TRY
BEGIN CATCH
IF (XACT_STATE()) <> 0
ROLLBACK TRAN
END CATCH
Si une lecture a lieu entre les deux instructions, elle peut trouver des dates de
paiement antérieures aux dates d’envoi, ce qui est une incohérence fonctionnelle.
Pour éviter cela, une lecture ne peut se faire que lorsqu’un verrou S est posé sur les
ressources. Ce verrou étant incompatible avec le verrou X, il doit attendre la libération des verrous X des ressources souhaitées.
Les verrous de type exclusifs (exclusive, X) sont des verrous d’écriture, posés sur
des lignes en cours de modification (INSERT, DELETE, UPDATE). Ils sont incompatibles
avec tout type de verrou, y compris eux-mêmes : quelles que soient les options de la
base ou de la session, il est interdit à deux transactions d’écrire simultanément les
mêmes ressources. Si cela était possible, ce serait le chaos 1 . On ne peut poser ni verrou exclusif, ni verrou partagé, etc., sur une ressource qui possède déjà un verrou
exclusif. On ne peut donc pas non plus lire une ligne en cours de modification, dans
un niveau d’isolation qui pose un verrou partagé à la lecture.
Les verrous de mise à jour (update, U) sont posés dans les niveaux d’isolation qui
maintiennent les verrous partagés toute la durée de la transaction (REPEATABLE READ
et SERIALIZABLE), ils permettent d’éviter une forme courante de verrou mortel (deadlock), lorsque la lecture sert, dans une instruction suivante, aux mises à jour. Dans
ce cas, le verrou partagé doit être converti en verrou exclusif. Mais, si une autre transaction maintient elle aussi des verrous partagés sur ces ressources, la première doit
1. Il existe sur certains SGBDR un niveau d’isolation de la transaction nommé CHAOS, qui permet les écritures simultanées. SQL Server ne le supporte pas. Le niveau d’isolation minimal est
READ UNCOMMITTED, comme nous le verrons plus loin.
