Question

Nous utilisons une base de données SQL Server 2005 (sans version de ligne) avec une instruction select énorme et nous constatons qu'elle bloque l'exécution d'autres instructions (constatée à l'aide de sp_who2 ). Je ne savais pas que les instructions SELECT pouvaient provoquer un blocage - puis-je faire quelque chose pour atténuer cela?

Était-ce utile?

La solution

SELECT peut bloquer les mises à jour. Un modèle de données et une requête correctement conçus ne provoqueront qu'un blocage minimal et ne constitueront pas un problème. Le conseil «habituel» AVEC NOLOCK est presque toujours la mauvaise réponse. La bonne solution consiste à ajuster votre requête afin qu'elle n'analyse pas les tables volumineuses.

Si la requête n’est pas optimisable, vous devez d’abord envisager le niveau d’isolation d’instantané , en second lieu, vous devriez envisager d’utiliser INSTANTANÉS DE LA BASE DE DONNÉES et la dernière option doit être DIRTY LIRE (et vaut mieux changer le niveau d'isolement plutôt que d’utiliser le CONSEIL NOLOCK). Notez que les lectures modifiées, comme le nom l'indique clairement, renverront des données incohérentes (par exemple, le nombre total de pages peut être déséquilibré).

Autres conseils

De la documentation :

  Les verrous

Shared (S) permettent aux transactions simultanées de lire (SELECT) une ressource sous un contrôle pessimiste de la simultanéité. Pour plus d'informations, voir Types de contrôle de concurrence . Aucune autre transaction ne peut modifier les données tant que des verrous shared (S) existent sur la ressource. Les verrous Shared (S) sur une ressource sont libérés dès que l'opération de lecture est terminée, à moins que le niveau d'isolation de transaction ne soit défini sur lecture ou supérieure, ou qu'un indice de verrouillage soit utilisé pour conserver le code . shared (S) verrouille pendant la durée de la transaction.

Un verrou partagé est compatible avec un autre verrou partagé ou un verrou de mise à jour, mais pas avec un verrou exclusif.

Cela signifie que vos requêtes SELECT vont bloquer les requêtes UPDATE et INSERT et inversement.

Une requête SELECT placera un verrou partagé temporaire lorsqu'elle lira un bloc de valeurs dans la table et le supprimera à la fin de la lecture.

Tant que le verrou n’existera pas, vous ne pourrez rien faire des données dans la zone verrouillée.

Deux requêtes SELECT ne se bloqueront jamais (sauf si elles sont SELECT FOR UPDATE )

Vous pouvez activer le niveau d'isolement SNAPSHOT sur votre base de données et l'utiliser, mais notez que cela n'empêchera pas les requêtes UPDATE d'être verrouillées par SELECT requêtes (ce qui semble être votre cas).

Cela empêchera cependant que les requêtes SELECT soient verrouillées par UPDATE .

Notez également que SQL Server , à la différence de Oracle , utilise le gestionnaire de verrous et le maintient verrouillé dans une liste liée en mémoire.

Cela signifie que sous une charge importante, le simple fait de placer et de supprimer un verrou peut être lent, car la liste liée doit elle-même être verrouillée par le fil de la transaction.

Pour effectuer des lectures modifiées, vous pouvez soit:

 using (new TransactionScope(TransactionScopeOption.Required, 
 new TransactionOptions { 
 IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
 {
 //Your code here
 }

ou

SelectCommand = "SELECT * FROM Table1 WITH (NOLOCK) INNER JOIN Table2 WITH (NOLOCK) ..."

rappelez-vous que vous devez écrire WITH (NOLOCK) après chaque table que vous souhaitez lire en lecture

Vous pouvez définir le niveau de transaction . lire sans engagement

Vous pouvez également obtenir des blocages:

"Blocages impliquant une seule table" http: // sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx

et ou résultats incorrects:

"Les sélections sous READ COMMITTED et REPEATABLE READ peuvent renvoyer des résultats incorrects."

http://www2.sqlblog.com/blogs/alexander_kuznetsov/archive/2009/04/10/selects-under-read-committed-and-repeatable-read-may-return -incorrect-results.aspx

Vous pouvez utiliser l'indicateur de table WITH (READPAST) . C'est différent du WITH (NOLOCK) . Il obtiendra les données avant le début de la transaction et ne bloquera personne. Imaginez que vous avez exécuté l'instruction avant le début de la transaction.

SELECT * FROM table1  WITH (READPAST)
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top