Quel est l'effet HOLDLOCK sur UPDLOCK?
J'ai vu de nombreux exemples de l'indicateur HOLDLOCK être utilisé en combinaison avec UPDLOCK (comme ceci). Cependant La documentation de Microsoft pour ces conseils faire paraître comme HOLDLOCK devrait être redondante, puisque UPDLOCK déjà persiste le verrou jusqu'à la fin de la transaction. (Aussi, il semble dire que HOLDLOCK s'applique uniquement aux verrous partagés de toute façon.)
Comment HOLDLOCK affecter la requête, le cas échéant?
Vous devez vous connecter pour publier un commentaire.
Il a un grand impact.
Le verrou de mise à Jour prend un verrou de mise à Jour sur la ligne, à l'Intention de mise à jour sur la page et un verrou partagé sur la table /base de données.
Cela n'empêche pas d'autres requêtes d'accès aux données dans le tableau, car les verrous sur la page /base de données sont purement part de serrures. Ils juste ne peut pas clash serrures à l'encontre de la personne de lignes /page /table en essayant d'effectuer une opération qui serait en contradiction avec les verrous. Si qui s'est déroulée à la demande dans la file d'attente derrière les verrous en cours et attendre qu'il vienne disponibles avant de pouvoir continuer.
En utilisant holdlock, la requête est contraint à être sérialisé, le verrouillage de la table exclusivement jusqu'à ce que l'action est terminée. Cela empêche tout le monde de la lecture de la table, sauf si l'indicateur nolock est utilisé, permettant potentiellement un sale lire.
Pour voir l'effet, de générer un exemple de tableau 'foo' et de mettre la poubelle des données.
Ouvrir une autre fenêtre et essayez:
Les lignes de revenir, maintenant commettre l'original de la requête de transaction. Exécutez de nouveau modifié pour utiliser holdlock ainsi:
Revenir à l'autre fenêtre et essayez de sélectionner à nouveau les données, la requête ne retourne pas de valeurs car il est bloqué par le verrou exclusif. Valider la transaction sur la première fenêtre, et les résultats de la deuxième requête apparaîtra, car il n'est plus bloqué.
Test Final est d'utiliser le nolock, exécutez de nouveau la transaction à l'aide de updlock et holdlock. ensuite, exécutez les opérations suivantes dans la deuxième fenêtre:
Les résultats reviendront automatiquement, puisque vous avez accepté de prendre le risque d'une sale de lecture (read).
Sorte qu'il est considéré avoir un grand impact, qui vous obligent les actions contre la table pour être sérialisé qui pourrait être ce que vous voulez (en fonction de la mise à jour à été faite) ou créera un très grand goulot d'étranglement sur la table. Si tout le monde a fait qu'à une table occupée avec de longues transactions en cours d'exécution, alors il serait la cause des retards importants au sein d'une application.
Comme avec toutes les fonctions SQL, lorsqu'il est utilisé correctement, ils peuvent être puissants, mais une mauvaise utilisation d'une fonction /indicateur peut causer des problèmes importants. Je préfère utiliser des indicateurs comme un dernier recours pour quand je dois remplacer le moteur - non pas comme une approche par défaut.
Modifier comme Demandé : Testé dans SQL 2005, 2008, 2008R2 (Entreprise) - tous installés sur à peu près les paramètres par défaut, test de la base de données créée à l'aide de tous les paramètres par défaut (juste entré le nom de la DB seulement).
set transaction isolation level read uncommitted
. Mais bien sûr, ça voudrait dire que la lecture des données qui pourrait bien ne jamais "réellement" dans la base de données.select * from foo
mais je ne vois blocage avec ma ", une nouvelle fenêtre de requête" commeselect * from foo with (updlock)
. Le type qui a du sens, si vous vous souciez de serialising des requêtes de prise de décisions sur l'opportunité de mettre à jour les lignes qu'ils lisent, ils devraient avoirupdlock
là quelque part. Disclaimer: je ne suis pas assaisonné à SQL Server de verrouillage.Andrew réponse est correcte conformément à la documentation MSDN, cependant j'ai testé contre 2008R2 et 2012, et je ne vois pas ce comportement, de sorte s'il vous plaît TESTER vous-même
Le comportement que je vois est comme ci-dessous:
De la première exécution de ce une pièce de la base de données.
...et de mettre quelques lignes dans.
Maintenant coller ce code dans les deux onglets requête (changer l'onglet " texte dans l'onglet de deux):
Et le mettre dans un autre tab 3:
Assurez-vous que votre pointage de votre jeu de données où la table est.
Mettre en évidence tout AVANT l'instruction de mise à jour dans onglet 1 et de l'exécuter.
De faire de même dans tab 2 vous trouverez tab 2 ne se termine PAS et est toujours en cours d'exécution.
Maintenant exécuter le simple SÉLECTIONNEZ dans tab 3 dans mon environnement, c'est terminé.
Mettre en évidence l'instruction de mise à jour dans onglet 1 et de l'exécuter (ne PAS faire le commit encore), vous verrez tab 2 est TOUJOURS en cours d'exécution.
Aller de l'avant et d'exécuter l'engagement dans onglet 1...tab 2 allons maintenant procéder à la sélection...vous pouvez exécuter le reste.