Edit: Comme le souligne @MaxVernon , ce qui suit n'est en aucun cas une suggestion d'utiliser NOLOCK , et j'aurais très bien dû mentionner la définition du niveau de transaction READ UNCOMMITEDet laisser la connotation négative se tenir là plutôt que d'évoquer NOLOCKen premier lieu. Donc, comme initialement affiché:
La réponse rapide et simple est "Oui, la première requête bloquera la deuxième requête, sauf si un indice d'index spécifique est spécifié ( NOLOCK , parfois appelé" lecture incorrecte ") ou si le niveau d'isolement des transactions de la deuxième requête est défini sur READ UNCOMMITED(qui fonctionne de manière identique), non."
En réponse aux détails supplémentaires fournis dans la question entraînant l'inclusion d'une WITHclause sur la seconde SELECT, s'excluant mutuellement ou non, les interactions entre les deux requêtes seront largement les mêmes.
IF NOT EXISTS ( SELECT 1
FROM sys.objects
WHERE name = 'Foo'
AND type = 'U' )
BEGIN
--DROP TABLE dbo.Foo;
CREATE TABLE dbo.Foo
(
Foo_PK BIGINT IDENTITY( 1, 1 ) NOT NULL,
PRIMARY KEY ( Foo_PK ),
Bar BIT,
x BIT,
y BIT,
z BIT
);
CREATE NONCLUSTERED INDEX IX_Foo_x
ON dbo.Foo ( x );
INSERT INTO dbo.Foo ( Bar, x, y, z )
VALUES ( 1, 1, 1, 1 ), ( 0, 0, 0, 0 );
END;
GO
BEGIN TRANSACTION;
UPDATE dbo.Foo
SET y = 0
WHERE x = 1;
-- COMMIT TRANSACTION;
Dans une session distincte, exécutez ce qui suit:
SELECT *
FROM dbo.Foo WITH ( NOLOCK );
GO
SELECT *
FROM dbo.Foo;
Vous pouvez examiner les verrous actuellement détenus en exécutant sp_lock, de préférence dans une autre session distincte:
EXECUTE dbo.sp_lock;
Vous devriez voir un KEYverrou de type détenu par le spid effectuant la transaction d'insertion en Xmode (exclusif), à ne pas confondre avec les autres IXverrous (Intent-Exclusive). La documentation du verrou indique que le KEYverrouillage est spécifique à la plage, mais il empêche également d'autres transactions d'insérer ou de mettre à jour les colonnes affectées en modifiant les données qui y sont contenues afin qu'elles puissent entrer dans cette plage de la requête d'origine. Le verrou lui-même étant exclusif, la première requête empêche l'accès à la ressource de toute autre transaction simultanée. En effet, toutes les lignes de la colonne sont verrouillées, qu'elles appartiennent ou non à la plage spécifiée par la première requête.
Le Sverrou détenu par la deuxième session sera donc WAITjusqu'à ce que le Xverrou soit effacé, empêchant un autre X(ou U) verrou d'être pris sur cette ressource à partir d'un spid simultané différent avant que la deuxième session ne termine son opération de lecture, justifiant l'existence du Sverrou.
Maintenant, une modification pour plus de clarté: à moins que je ne me trompe dans ce qu'est une lecture sale de la brève description des risques mentionnés ici ... Edit 3 : Je viens de réaliser que je ne considère pas l'effet d'un point de contrôle de fond qui écrit un comme de transaction encore non validée sur le disque, donc oui, mon explication était trompeuse.
Dans la deuxième requête, le premier lot peut (et dans ce cas, renverra) des données non validées. Le deuxième lot, exécuté au niveau d'isolation de transaction par défaut de, READ COMMITEDne sera renvoyé qu'après la fin d'une validation ou d'une restauration dans la première session.
À partir d'ici, vous pouvez consulter vos plans de requête et les niveaux de verrouillage associés, mais mieux encore, vous pouvez lire tout sur les verrous dans SQL Server ici .
SELECT * FROM Table1si c'est exactement ce dont j'ai besoin?