J'utilise SQL Server 2005 Express.
Dans un scénario, j'ai ajouté une Begin Transaction
commande juste avant une INSERT
instruction dans une procédure stockée. Lorsque j'ai exécuté cette procédure stockée, elle a verrouillé toute la table et toutes les connexions simultanées ont affiché un affichage bloqué jusqu'à ce que cela se INSERT
termine.
Pourquoi la table entière est-elle verrouillée et comment résoudre ce problème dans SQL Server 2005 Express?
Édité
La requête est comme ci-dessous:
INSERT INTO <table2> SELECT * FROM <table1> WHERE table1.workCompleted = 'NO'
Réponses:
Cette réponse peut s'avérer utile pour la question d'origine, mais vise principalement à corriger des informations inexactes dans d'autres publications. Il met également en évidence une section de non-sens dans BOL.
La section liée de BOL indique:
NB: Depuis le 2014-8-27, BOL a été mis à jour pour supprimer les déclarations incorrectes citées ci-dessus.
Heureusement, ce n'est pas le cas. S'il en était ainsi, les insertions dans une table se produiraient en série et tous les lecteurs seraient bloqués de la table entière jusqu'à la fin de la transaction d'insertion. Cela ferait de SQL Server un serveur de base de données aussi efficace que NTFS. Pas très.
Le bon sens suggère qu'il ne peut en être ainsi, mais comme le souligne Paul Randall, " Rendez-vous service, ne faites confiance à personne ". Si vous ne pouvez faire confiance à personne, y compris BOL , je suppose que nous devrons simplement le prouver.
Créez une base de données et remplissez une table fictive avec un tas de lignes, en notant le DatabaseId renvoyé.
Configurez une trace de profileur qui suivra les événements de verrouillage: acquis et de verrouillage: libéré, filtrage sur le DatabaseId à partir du script précédent, définition d'un chemin d'accès au fichier et notant le TraceId renvoyé.
Insérez une ligne et arrêtez la trace:
Ouvrez le fichier de trace et vous devriez trouver ce qui suit:
La séquence de verrous pris est:
Les verrous sont ensuite libérés dans l'ordre inverse. À aucun moment un verrou exclusif n'a été acquis sur la table.
Oui, ça l'est. SQL Server (et sans doute tout moteur de base de données relationnelle) ne sait pas quels autres lots peuvent être exécutés lorsqu'il traite une instruction et / ou un lot, de sorte que la séquence d'acquisition des verrous ne varie pas.
Pour cet exemple particulier, exactement les mêmes verrous sont pris. Ne me faites pas confiance, essayez-le!
la source
Je ne fais pas beaucoup de travail T-SQL mais à la lecture de la documentation ...
C'est par conception, comme indiqué dans la transaction de début :
Et comme indiqué pour la documentation INSERT , il obtiendra un verrou exclusif sur la table. La seule façon d'effectuer un SELECT sur la table est d'utiliser
NOLOCK
ou de définir le niveau d'isolement de la transaction.la source