Quelqu'un peut-il expliquer pourquoi choisir avec nolock va interroger une potion de données mises à jour?
-
16-10-2019 - |
Question
Je lisais la réponse de ici (de StackOverflow, je pense, devrait demander ici)
moyens de NOLOCK placer aucune serrure du tout.
Votre requête peut renvoie des portions de données sous forme de UPDATE et avant des parties relevées après mise à jour dans une seule requête.
Je reçois que nolock ne placerai pas serrure à la table, pour que d'autres personnes peuvent interroger en même temps.
De la réponse et l'exemple qu'il montre, il récupérer les données alors que les données sont mises à jour.
Pourquoi est-ce que cela se produise?
Je suppose pour sélectionner la normale va essayer de verrouillage sur la table lieu, donc quand la déclaration de mise à jour est exécuté, il placer un verrou sur la ligne ou la page. Puis, quand je tente d'exécuter l'instruction select, il ne peut pas mettre le verrou jusqu'à ce que le verrou de la déclaration de mise à jour est publiée.
Mais dans ce cas parce que l'instruction select ne cherche pas à mettre verrou sur la table, il peut courir sans attendre la déclaration de mise à jour libérer le verrou?
La solution
Il est pas tout à fait vrai que des moyens de NOLOCK
placer aucune serrure du tout. Les requêtes sous cette indication prendra encore des verrous de Sch-S
et ( éventuellement verrouille HOBT
).
Dans le niveau d'isolement de read committed
SQL Server ( habituellement ) prendre les verrous de S
de niveau ligne et de les libérer dès que les données sont lues. Ceux-ci sont incompatibles avec les verrous de X
détenus sur les mises à jour UNCOMMITED et empêchent ainsi se lit sale.
Dans l'exemple dans la réponse liée à la requête de SELECT
n'est pas bloqué quand il rencontre une ligne modifiée afin de lire les mises à jour partielles est tout à fait probable.
Il peut également se produire au niveau d'isolement par défaut read committed
aussi bien qu'un SELECT
lit quelques lignes avec le « avant » la valeur et d'autres avec la valeur « après ». Il est tout simplement nécessaire pour concevoir une situation où
- Sélectionnez la requête lit la valeur de la ligne
R1
et libère son verrou deS
- Mise à jour des mises à jour de la requête
R2
et prend un verrouX
- Sélectionner tente de requête pour lire
R2
et est bloqué. - Mise à jour des mises à jour de la requête
R1
et prend un verrouX
. - Mise à jour commits de transaction libérant ainsi ses verrous et permettant Select lire
R2
Ce type de situation peut se produire par exemple si le SELECT
et UPDATE
utilisent différents indices pour localiser les lignes d'intérêt.
Exemple
CREATE TABLE T
(
X INT IDENTITY PRIMARY KEY,
Y AS -X UNIQUE,
Name varchar(10),
Filler char(4000) DEFAULT 'X'
)
INSERT INTO T (Name)
SELECT TOP 2500 'A'
FROM master..spt_values
Maintenant en une seule fois la fenêtre de requête
DECLARE @Sum int
SELECT 'SET @@ROWCOUNT' WHERE 1=0
WHILE (@@ROWCOUNT = 0)
SELECT @Sum = SUM(LEN(Name))
FROM T
WHERE Y IN (-1, -2500)
HAVING SUM(LEN(Name)) = 3
se déroulera dans une boucle infinie. Dans un autre essai
UPDATE T
SET Name=CASE WHEN Name = 'A' THEN 'AA' ELSE 'A' END
Cela arrêtera probablement la boucle dans l'autre requête (essayez à nouveau sinon) ce qui signifie qu'il doit avoir lu soit A,AA
ou AA,A
Autres conseils
Le NOLOCK
indice est équivalent au niveau de l'isolation de transaction READ UNCOMMITTED
, juste limitée à la portée d'un procédé d'accès de tableau.
Qu'est-ce que RU ne qui fait la non-commis apparaissent sur votre resultset? Hmm, est en fait une question de « ce qu'il fait pas . Je vais vous expliquer ci-dessous.
Eh bien (ce qui est une simplification grossière, je sais) MSSQL (dans son comportement par défaut) est un moteur de verrouillage - ce qui signifie qu'il utilise serrure pour lire / écrire des données sur une manière cohérente. Dans cette explication simplificatrice, MSSQL utilise deux types de serrures: verrou partagé et verrou exclusif .
Un partage de verrouillage (S) est un verrou qui permet une ressource (qui peut être une ligne, page de lignes ou même une table entière) à lire - mais pas permet d'écrire. Donc, si la transaction T1 met un verrou S sur la ligne R1, toutes les transactions qui essaie de lire R1 obtenir cette lecture, mais alors que le verrou S est en vie que personne ne peut écrire à R1.
Un verrou exclusif (X) est la contrepartie de la serrure commune. Il permet un accès exclusif à une ressource - aucune autre transaction ne peut lire ou écrire, sauf celui qui a obtenu le verrou X. Dans l'exemple ci-dessus, si T1 a pas un verrou S mais un verrou X sur R1, ne sauf T1 peut lire ou écrire.
C'est le teory. Les niveaux d'isolement respectent les serrures, et respectent leur prévalence et les caractéristiques. Tous, à l'exception READ UNCOMMITTED
. Simple donne un * (mettre votre mot mauvaise bouche de votre préférence ici) aux serrures en ce qui concerne la lecture - vous ne pouvez toujours pas mettre à jour la ligne une autre transaction a un verrou X. Il dit simplement: « Je vais lire tout ce qui est pertinent pour le plan de requête - Méconnaissance ce que les serrures sont là-dessus. »
Et le faire.