web-dev-qa-db-fra.com

Blocages SQL Server entre sélection / mise à jour ou sélections multiples

Toute la documentation sur les blocages SQL Server parle du scénario dans lequel l'opération 1 verrouille la ressource A puis tente d'accéder à la ressource B et l'opération 2 verrouille la ressource B et tente d'accéder à la ressource A.

Cependant, je vois assez souvent des blocages entre une sélection et une mise à jour ou même entre plusieurs sélections dans certaines de nos applications occupées. Je trouve que certains des points les plus fins de la sortie de trace de blocage sont assez impénétrables, mais j'aimerais vraiment comprendre ce qui peut provoquer un blocage entre deux opérations simples. Sûrement, si une sélection a un verrou en lecture, la mise à jour devrait simplement attendre avant d'obtenir un verrou exclusif et vice versa?

Cela se produit sur SQL Server 2005, pas que je pense que cela fait une différence.

37
Rob West

Une fois, j'ai mis en signet un bon article sur verrouillage avancé de SQL Server sur SQL-Server-Performance.com. Cet article va au-delà de la situation de blocage classique que vous avez mentionnée et pourrait vous donner un aperçu de votre problème.

13
MicSim

Cela peut se produire car une sélection prend un verrouillage sur deux index différents, tandis qu'une mise à jour prend un verrouillage sur les mêmes index dans l'ordre inverse. La sélection a besoin de deux index car le premier index ne couvre pas toutes les colonnes auxquelles il a besoin d'accéder; la mise à jour a besoin de deux index, car si vous mettez à jour la colonne de clé d'un index, vous devez le verrouiller.

http://blogs.msdn.com/bartd/archive/2006/09/25/770928.aspx a une explication fantastique. Les correctifs suggérés incluent l'ajout d'un index qui couvre toutes les colonnes dont la sélection a besoin, le passage à l'isolement d'instantané ou le forçage explicite de la sélection à récupérer un verrou de mise à jour dont il n'aurait normalement pas besoin.

20
David Eison

Je suis surpris que personne n'ait mentionné le conseil de verrouillage WITH (UPDLOCK). C'est très utile si vous avez des blocages impliquant par exemple deux paires d'insertion-sélection fonctionnant en parallèle.

Dans SQL Server, si vous émettez les sélections avec WITH (UPDLOCK), la deuxième sélection attendra jusqu'à ce que la première sélection soit terminée. Sinon, ils obtiennent des verrous partagés et lorsqu'ils tentent simultanément de passer à des verrous exclusifs, ils bloquent.

13
Ben Challenor

Des verrous entre des requêtes uniques peuvent se produire car ils verrouillent des lignes uniques, pas la table entière:

La requête de mise à jour obtient un verrou de mise à jour sur quelques lignes d'une table et la requête de sélection obtient un verrou de lecture sur certaines autres lignes de la table. La requête de mise à jour essaie ensuite d'obtenir un verrou de mise à jour sur les lignes verrouillées en lecture et la requête de sélection tente d'obtenir un verrou de lecture sur les lignes verrouillées.

Cela peut devenir encore plus compliqué avec l'escalade des verrous, c'est-à-dire que la base de données décide qu'il y a trop de lignes uniques verrouillées par une transaction afin qu'elle devrait être escaladée pour verrouiller une section de la table ou la table entière. Cela signifie que le verrou peut affecter les lignes qui ne sont pas directement impliquées dans la requête.

5
Guffa

Ma conjecture est que l'instruction select acquiert un verrou de lecture, lorsque vous venez avec l'instruction update, alors elle doit passer à un verrou d'écriture.

La mise à niveau vers un verrou en écriture nécessite que tous les autres verrous en lecture soient supprimés (leurs transactions de sélection se terminent). Mais si un autre processus a déjà la brillante idée de passer à un verrou en écriture, vous avez soudainement deux processus en attente pour libérer le verrou en lecture, afin qu'ils puissent obtenir le verrou en écriture.

Si vous utilisez select-for-update (UPDLOCK), il acquiert un verrouillage en écriture depuis le début et vous n'avez pas le problème de blocage.

5
Rolf Kristensen

Lisez correctement les transactions et les niveaux d'isolement: pour un travail quelque peu dense mais assez approfondi et neutre sur le plan technologique, voir Principes du traitement des transactions . Cela a secoué mon monde (et m'a donné pas mal de maux de tête!).

Je ne sais pas avec quoi vous avez des problèmes, ni avec quel niveau d'isolement vous utilisez. Mais considérez ceci: pour tout le moteur de base de données sait, si vous effectuez des lectures dans une transaction, comment peut-il dire si vous allez ou non faire une écriture plus tard? Des niveaux d'isolation élevés nécessitent un verrouillage chaque fois qu'une lecture est effectuée, éventuellement sur toute la table pour se protéger contre les lectures fantômes, car les données peuvent affecter une écriture plus tard.

Souhaitez-vous que la base de données attende arbitrairement longtemps pour un verrouillage exclusif sur vos données? Jetez un œil à vos niveaux d'isolement et vérifiez si vous exécutez inutilement une série de lectures en tant que transaction isolée. Cependant, il n'est pas toujours facile de déterminer à quel point les lectures sales peuvent être tolérées ...

1
Pontus Gagge

Vous devez lire sur l'isolation des transactions: http://msdn.Microsoft.com/en-us/library/ms173763.aspx

0
James L