Lors de mes recherches sur l'utilisation de Conseils de table , je suis tombé sur ces deux questions:
Les réponses aux deux questions indiquent que, lorsque vous utilisez (UPDLOCK, HOLDLOCK)
, les autres processus ne pourront pas lire les données sur cette table, mais je ne l’ai pas vu. Pour tester, j'ai créé une table et démarré deux fenêtres SSMS. À partir de la première fenêtre, j'ai exécuté une transaction qui a été sélectionnée dans le tableau à l'aide de différents indicateurs de tableau. Pendant que la transaction était en cours, à partir de la deuxième fenêtre, j’ai exécuté diverses instructions pour voir lesquelles seraient bloquées.
La table de test:
CREATE TABLE [dbo].[Test](
[ID] [int] IDENTITY(1,1) NOT NULL,
[Value] [nvarchar](50) NULL,
CONSTRAINT [PK_Test] PRIMARY KEY CLUSTERED
(
[ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
Depuis la fenêtre 1 de SSMS:
BEGIN TRANSACTION
SELECT * FROM dbo.Test WITH (UPDLOCK, HOLDLOCK)
WAITFOR DELAY '00:00:10'
COMMIT TRANSACTION
À partir de la fenêtre 2 de SSMS (l’une des opérations suivantes):
SELECT * FROM dbo.Test
INSERT dbo.Test(Value) VALUES ('bar')
UPDATE dbo.Test SET Value = 'baz' WHERE Value = 'bar'
DELETE dbo.Test WHERE Value= 'baz'
Effet de différentes indications de table sur les instructions exécutées dans la fenêtre 2:
(UPDLOCK) (HOLDLOCK) (UPDLOCK, HOLDLOCK) (TABLOCKX)
---------------------------------------------------------------------------
SELECT not blocked not blocked not blocked blocked
INSERT not blocked blocked blocked blocked
UPDATE blocked blocked blocked blocked
DELETE blocked blocked blocked blocked
Ai-je mal compris les réponses données dans ces questions ou fait une erreur dans mes tests? Sinon, pourquoi utiliseriez-vous (UPDLOCK, HOLDLOCK)
contre. (HOLDLOCK)
seul?
Explication supplémentaire de ce que j'essaie d'accomplir:
Je souhaite sélectionner des lignes dans une table et empêcher que les données de cette table ne soient modifiées pendant que je les traite. Je ne modifie pas ces données et souhaite autoriser les lectures.
Cette réponse dit clairement que (UPDLOCK, HOLDLOCK)
bloquera les lectures (pas ce que je veux). Les commentaires sur cette réponse impliquent que c’est HOLDLOCK
qui empêche les lectures. Pour essayer de mieux comprendre les effets des indications de table et voir si UPDLOCK
ferait seul ce que je voulais, j'ai effectué l'expérience ci-dessus et obtenu des résultats contredisant ces réponses.
Actuellement, je crois que (HOLDLOCK)
est ce que je devrais utiliser, mais je crains d’avoir commis une erreur ou d’avoir oublié quelque chose qui va me revenir dans l’avenir, d’où cette question.
Pourquoi le bloc UPDLOCK choisit-il? La matrice de compatibilité des verrous indique clairement N
pour les conflits S/U et U/S, comme dans Pas de conflit .
Pour ce qui est du HOLDLOCK , la documentation indique:
HOLDLOCK: est équivalent à SERIALIZABLE. Pour plus d'informations, voir SERIALIZABLE plus loin dans cette rubrique.
...
SERIALIZABLE: ... L'analyse est effectuée avec la même sémantique qu'une transaction exécutée au niveau d'isolement SERIALIZABLE ...
et la rubrique niveau d’isolation de transaction explique ce que SERIALIZABLE signifie:
Aucune autre transaction ne peut modifier les données lues par la transaction en cours jusqu'à la fin de la transaction en cours.
D'autres transactions ne peuvent pas insérer de nouvelles lignes avec des valeurs de clé comprises dans la plage de clés lues par les instructions de la transaction en cours jusqu'à la fin de la transaction en cours.
Par conséquent, le comportement que vous voyez est parfaitement expliqué par la documentation du produit:
SELECT * FROM dbo.Test WITH (UPDLOCK) WHERE ...
La vraie question est qu'essayez-vous de réaliser? Jouer avec des astuces de verrouillage sans une compréhension totale et absolue de 110% de la sémantique du verrouillage est en quête de problèmes ...
Après la modification de l'OP:
Je souhaite sélectionner des lignes dans une table et empêcher que les données de cette table ne soient modifiées pendant que je les traite.
Vous devez utiliser l'un des niveaux d'isolation de transaction les plus élevés. REPEATABLE READ empêchera les données lues d'être modifiées. SERIALIZABLE empêchera que les données lues soient modifiées et de nouvelles données soient insérées. L'utilisation de niveaux d'isolation de transaction est la bonne approche, par opposition à l'utilisation d'indicateurs de requête. Kendra Little a ne affiche de Nice illustrant les niveaux d’isolement .
UPDLOCK est utilisé lorsque vous souhaitez verrouiller une ou plusieurs lignes lors d'une instruction de sélection pour une instruction de mise à jour future. La prochaine mise à jour pourrait être la prochaine instruction de la transaction.
D'autres sessions peuvent toujours voir les données. Ils ne peuvent tout simplement pas obtenir de verrous incompatibles avec UPDLOCK et/ou HOLDLOCK.
Vous utilisez UPDLOCK lorsque vous souhaitez empêcher d'autres sessions de modifier les lignes que vous avez verrouillées. Cela limite leur capacité à mettre à jour ou à supprimer des lignes verrouillées.
Vous utilisez HOLDLOCK lorsque vous souhaitez empêcher d'autres sessions de modifier les données que vous consultez. Cela limite leur capacité à insérer, mettre à jour ou supprimer les lignes que vous avez bloquées. Cela vous permet d'exécuter la requête à nouveau et de voir les mêmes résultats.