Quelqu'un peut-il expliquer pourquoi choisir avec nolock va interroger une potion de données mises à jour?

dba.stackexchange https://dba.stackexchange.com/questions/11571

  •  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?

Était-ce utile?

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ù

  1. Sélectionnez la requête lit la valeur de la ligne R1 et libère son verrou de S
  2. Mise à jour des mises à jour de la requête R2 et prend un verrou X
  3. Sélectionner tente de requête pour lire R2 et est bloqué.
  4. Mise à jour des mises à jour de la requête R1 et prend un verrou X.
  5. 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.

Licencié sous: CC-BY-SA avec attribution
Non affilié à dba.stackexchange
scroll top