TABLOCK vs TABLOCKX
Quelle est la différence entre TABLOCK
et TABLOCKX
http://msdn.microsoft.com/en-us/library/ms187373.aspx stipule que TABLOCK
est un verrou partagé tout TABLOCKX
est un verrou exclusif. Le premier peut-être seulement un verrou d'index de toutes sortes? Et quel est le concept de partage d'une serrure?
3 réponses
Grande différence, TABLOCK
va essayer de saisir des verrous "partagés", et TABLOCKX
verrous exclusifs.
Si vous êtes dans une transaction et que vous prenez un verrou exclusif sur une table, par exemple:
SELECT 1 FROM TABLE WITH (TABLOCKX)
Aucun autre processus ne pourra saisir aucun verrou sur la table, ce qui signifie que toutes les requêtes qui tentent de parler à la table seront bloquées jusqu'à ce que la transaction soit validée.
TABLOCK
ne saisit qu'un verrou partagé, les verrous partagés sont libérés après qu'une instruction est exécuté si votre isolation de transaction est READ COMMITTED
(par défaut). Si votre niveau d'isolement est supérieur, par exemple: SERIALIZABLE
, verrous partagés sont maintenus jusqu'à la fin d'une transaction.
Les verrous partagés sont, hmmm, partagés. Ce qui signifie que 2 transactions peuvent à la fois lire les données de la table en même temps si elles détiennent toutes les deux un verrou s ou IS sur la table (via TABLOCK
). Toutefois, si transaction A
détient un verrou partagé sur une table, transaction B
ne pourra pas saisir un verrou exclusif tant que tous les verrous partagés publier. Lisez à propos de quels verrous sont compatibles avec which à msdn .
Les deux astuces font que la base de données évite de prendre des verrous plus granulaires (comme des verrous de ligne ou de page). En principe, des verrous plus granulaires vous permettent une meilleure concurrence. Ainsi, par exemple, une transaction pourrait mettre à jour la ligne 100 dans votre table et une autre ligne 1000, en même temps à partir de deux transactions (cela devient difficile avec les verrous de page, mais permet de sauter cela).
En général, les serrures granulaires sont ce que vous voulez, mais parfois vous pouvez réduire la concurrence db pour augmenter les performances d'une opération particulière et éliminer le risque de blocages.
En général, vous n'utiliseriez pas TABLOCK
ou TABLOCKX
sauf si vous en aviez absolument besoin pour un cas de bord.
Un vieil article sur mssqlcity tente d'expliquer les types de verrous:
Les verrous partagés sont utilisés pour les opérations qui ne modifient pas ou ne mettent pas à jour les données, telles qu'une instruction SELECT.
Les verrous de mise à jour sont utilisés lorsque SQL Server a l'intention de modifier une page, puis promeut le verrou de page de mise à jour en un verrou de page exclusif avant d'effectuer les modifications.
Les verrous exclusifs sont utilisés pour les opérations de modification de données, telles que UPDATE, INSERT ou SUPPRIMER.
Ce qu'il ne discute pas est L'intention (qui est essentiellement un modificateur pour ces types de verrous). Les verrous d'intention (partagés/exclusifs) sont des verrous maintenus à un niveau supérieur au verrou réel. Ainsi, par exemple, si votre transaction a un verrou X sur une ligne, elle aura également un verrou IX au niveau de la table (ce qui empêche les autres transactions d'essayer d'obtenir un verrou incompatible à un niveau supérieur sur la table (par exemple un verrou de modification de schéma) jusqu'à ce que votre transaction soit terminée ou arrière).
Le concept de "partage" d'un verrou est assez simple - plusieurs transactions peuvent avoir un verrou partagé pour la même ressource, alors qu'une seule transaction peut avoir un verrou exclusif, et un verrou exclusif empêche toute transaction d'obtenir ou de conserver un verrou partagé.
C'est plus un exemple où TABLOCK n'a pas fonctionné pour moi et TABLOCKX l'a fait.
J'ai 2 sessions, qui utilisent toutes les deux le niveau d'isolement par défaut (READ COMMITTED):
La Session 1 est une transaction explicite qui copie les données d'un serveur lié vers un ensemble de tables dans une base de données, et prend quelques secondes pour s'exécuter. [Exemple, il supprime les Questions] La Session 2 est une instruction insert, qui insère simplement des lignes dans une table à laquelle la Session 1 n'apporte pas de modifications. [Par exemple, il insère Réponse].
(en pratique, il y a plusieurs sessions insérant plusieurs enregistrements dans la table, simultanément, pendant que la Session 1 exécute sa transaction).
La Session 1 doit interroger la table dans laquelle la Session 2 est insérée car elle ne peut pas supprimer les enregistrements qui dépendent des entrées ajoutées par la Session 2. [Exemple: supprimer les questions qui n'ont pas reçu de réponse].
Ainsi, alors que la Session 1 est en cours d'exécution et que la Session 2 essaie d'insérer, la Session 2 perd dans une impasse tous les temps.
Ainsi, une instruction delete dans la Session 1 peut ressembler à ceci: Supprimer tblA de TBLQ gauche rejoindre tblx sur ... Gauche rejoindre tblA a sur tblQ.Qid = tblA.Qid OÙ ... un.QId EST NULLE et ...
L'impasse semble être causée par une contention entre l'interrogation de tblA pendant la Session 2, [3, 4, 5, ..., n] essayez d'insérer dans tblA.
Dans mon cas, je pourrais changer le niveau d'isolement de la transaction de la Session 1 pour QU'elle soit sérialisable. Quand je l'ai fait: le gestionnaire de transactions a désactivé son support pour les transactions distantes/réseau.
Donc, je pourrais suivre les instructions dans la réponse acceptée ici pour le contourner: le gestionnaire de transactions a désactivé son support pour les transactions distantes/réseau
Mais a) je n'étais pas à l'aise de changer le niveau D'isolement en sérialisable en premier lieu - soi-disant cela dégrade les performances et peut avoir d'autres conséquences que je n'ai pas considérées, b) Je n'ai pas compris pourquoi cela a soudainement causé le transaction pour avoir un problème de travail sur les serveurs liés, et c) ne sais pas quels trous possibles je pourrais ouvrir en activant l'accès au réseau.
Il semblait y avoir seulement 6 requêtes dans une très grande transaction qui causent le problème.
Donc, j'ai lu à propos de TABLOCK et TabLOCKX.
Je n'étais pas clair sur les différences, et je ne savais pas si l'un ou l'autre fonctionnerait. Mais il semblait que ce serait. J'ai d'abord essayé TABLOCK et cela ne semblait pas faire de différence. Le concurrents ont suscité les mêmes blocages. Ensuite, J'ai essayé TABLOCKX, et plus de blocages.
Donc, à six endroits, tout ce que j'avais à faire était d'ajouter un avec (TABLOCKX).
Ainsi, une instruction delete dans la Session 1 peut ressembler à ceci: Supprimer tblA de TBLQ Q gauche rejoindre tblx X on ... Gauche rejoindre tblA A avec (TABLOCKX) sur tblQ.Qid = tblA.Qid OÙ ... un.QId EST NULLE et ...