Est-ce que le NOLOCK (indice de serveur SQL) est une mauvaise pratique?

125

Je suis dans le domaine de la création de sites Web et d'applications qui ne sont pas critiques -> par exemple. logiciel bancaire, vol spatial, application de suivi de soins intensifs, etc. Vous voyez l'idée.

Donc, avec cette énorme clause de non-responsabilité, est-ce mal d'utiliser l'indication NOLOCK dans une instruction SQL? Il y a quelques années, un collègue administrateur Sql m'a suggéré d'utiliser NOLOCK si je suis satisfait d'une «lecture sale» qui me donnera un peu plus de performances sur mon système car chaque lecture ne verrouille pas le table / ligne / peu importe.

On m'a également dit que c'était une excellente solution si je rencontrais des impasses. Donc, j'ai commencé à suivre cette pensée pendant quelques années jusqu'à ce qu'un gourou Sql m'aide avec du code aléatoire et remarque tous les NOLOCKS dans mon code SQL. J'ai été poliment grondé et il a essayé de me l'expliquer (pourquoi ce n'est pas une bonne chose) et je me suis un peu perdu. J'ai senti que l'essence de son explication était «c'est une solution de fortune à un problème plus grave… surtout si vous êtes dans une impasse. En tant que tel, corrigez la racine du problème '.

J'ai récemment cherché sur Google à ce sujet et je suis tombé sur ce post .

Alors, est-ce que certains Sensei de SQL DB Guru peuvent m'éclairer?

Pure.Krome
la source
Je ne comprends pas Sam, vous dites d'utiliser l'isolement Snapshot s'il s'agit d'un site Web à lecture intensive. Mais tu dis alors que tu as fait ça, et c'est mauvais? ou simplement leur utilisation de NOLOCK?
Pure.Krome

Réponses:

67

Avec l'indicateur NOLOCK, le niveau d'isolement de transaction pour l' SELECTinstruction est READ UNCOMMITTED. Cela signifie que la requête peut voir des données sales et incohérentes.

Ce n'est pas une bonne idée d'appliquer en règle générale. Même si ce comportement de lecture sale convient à votre application Web critique, une analyse NOLOCK peut provoquer une erreur 601 qui mettra fin à la requête en raison du mouvement des données en raison du manque de protection de verrouillage.

Je suggère de lire When Snapshot Isolation Helps and When It Hurts - le MSDN recommande d'utiliser READ COMMITTED SNAPSHOT plutôt que SNAPSHOT dans la plupart des circonstances.

Poneys OMG
la source
1
Rex, n'hésitez pas à ajouter une note sur l'isolement des instantanés.
Sam Saffron
2
Ouais, Sam parle d'isolement de snapshot et vous suggérez de lire un snapshot validé. Je deviens si confus: P (et je n'ai pas encore fouillé dans les articles, aussi!)
Pure.Krome
2
Il est parfois utile, mais pas normalement pour la production. Je l'utilise fréquemment pour extraire un échantillon de données à tester ou pour générer des rapports où je me soucie principalement de l'ordre de grandeur approximatif où une lecture sale n'aura pas d'importance.
TimothyAWiseman
NOLOCK == Je me fiche de savoir si des lignes validées sont manquées, des lignes non validées sont incluses, dans de rares cas, la même ligne est retournée plus d'une fois, et dans de très rares cas, des lignes sont renvoyées qui ne correspondent pas à ma requête. (voir blogs.msdn.com/b/sqlcat/archive/2007/02/01/… , trouvé à partir d'un autre SO q'n sur ce sujet)
Andrew Hill
106

Avant de travailler sur Stack Overflow, j'étais contre NOLOCKle principe avec lequel vous pourriez potentiellement effectuer un SELECTavec NOLOCKet obtenir des résultats avec des données qui peuvent être obsolètes ou incohérentes. Un facteur à prendre en compte est le nombre d'enregistrements qui peuvent être insérés / mis à jour en même temps qu'un autre processus peut sélectionner des données dans la même table. Si cela se produit souvent, il y a une forte probabilité de blocages, sauf si vous utilisez un mode de base de données tel que READ COMMITED SNAPSHOT.

Depuis, j'ai changé ma perspective sur l'utilisation de NOLOCKaprès avoir vu comment il peut améliorer les SELECTperformances et éliminer les blocages sur un serveur SQL massivement chargé. Il y a des moments où vous ne vous souciez pas du fait que vos données ne sont pas exactement engagées à 100% et que vous avez besoin de résultats rapidement, même s'ils ne sont pas à jour.

Posez-vous une question lorsque vous envisagez d'utiliser NOLOCK:

Ma requête inclut-elle une table qui a un nombre élevé de commandes INSERT/ UPDATEet est-ce que je me soucie si les données renvoyées par une requête peuvent manquer ces modifications à un moment donné?

Si la réponse est non, utilisez NOLOCKpour améliorer les performances.


Je viens d'effectuer une recherche rapide du NOLOCKmot - clé dans la base de code de Stack Overflow et j'ai trouvé 138 instances, nous l'utilisons donc dans de nombreux endroits.

Geoff Dalgas
la source
7
OMI, c'est un peu simpliste. Les blocages peuvent être supprimés à l'aide d'index de recouvrement, ce qui réduit la pression de l'index groupé.
Mitch Wheat
8
Je ne souhaite pas diminuer l'importance d'une bonne couverture indicielle. Il arrive que les requêtes utilisant NOLOCK puissent ajouter des performances supplémentaires en plus des gains réalisés par les index sur des tables avec un nombre élevé d'insertions / mises à jour. La vitesse de requête sur Stack Overflow est primordiale, même au prix de données inexactes ou manquantes.
Geoff Dalgas
9
Apparemment, on peut obtenir des lignes en double en utilisant NOLOCK. Cela signifie que je dois voter contre votre réponse. Désolé.
ErikE
1
@MitchWheat A SELECT, en lecture uniquement à partir d'un index de couverture, peut provoquer un blocage. SPID 1) commencez a à SELECTpartir de l'index de couverture. SPID 2) Démarrez un UPDATEde la table. La mise à jour passe ensuite à la mise à jour de l'index de couverture. UPDATEatteint une plage d'index verrouillée par SELECTet devient bloquée. SPID 1) recherche toujours dans l'index de couverture, trouve une plage verrouillée par le UPDATEet devient bloquée. DEADLOCK . Rien ne peut résoudre ce blocage (à l'exception de la capture de l'erreur SQL Server 1205 et d'une nouvelle tentative automatique ou de l'utilisation NOLOCK)
Ian Boyd
2
Je pense que la chose importante à noter à propos de cette réponse est qu'elle était adaptée au problème en question . En fonction de votre application, le risque de données périmées / non validées / dupliquées / manquantes peut ne pas valoir le compromis.
Développeur holistique
20

Si vous ne vous souciez pas des lectures sales (c'est-à-dire dans une situation de LECTURE prédominante), alors NOLOCKc'est bien.

MAIS , sachez que la majorité des problèmes de verrouillage sont dus à l'absence d'index «corrects» pour votre charge de travail de requête (en supposant que le matériel soit à la hauteur de la tâche).

Et l'explication du gourou était correcte. Il s'agit généralement d'une solution temporaire à un problème plus grave.

Edit : Je ne suggère certainement pas que NOLOCK devrait être utilisé. J'imagine que j'aurais dû le dire clairement. (Je ne l'utiliserais jamais, dans des circonstances extrêmes où j'avais analysé que c'était OK). A titre d'exemple, il y a quelque temps, j'ai travaillé sur un TSQL qui avait été saupoudré de NOLOCK pour essayer d'atténuer les problèmes de verrouillage. Je les ai tous supprimés, implémenté les index corrects et TOUS les blocages ont disparu.

Blé Mitch
la source
3
Hmm ... je ne comprends toujours pas. Alors ça va, mais c'est aussi une mauvaise forme ... c'est ce que tu dis?
Pure.Krome
En supposant que vous ne vous souciez JAMAIS des lectures sales, cela ne fera pas de mal. MAIS il s'agit généralement de traiter le symptôme et non la cause ...
Mitch Wheat
2
Eh bien, je ne pense pas que son juste rexem ait simplement été critiqué, je pense que vous n'avez pas abordé les erreurs arbitraires qui flottent simplement lorsque vous utilisez nolock. Ce n'est pas bien d'avoir une page d'erreur vierge de temps en temps sur votre site Web, c'est vraiment une mauvaise forme. Je n'aime pas l'affirmation selon laquelle "si vous ne vous souciez pas des lectures sales, c'est bien" ... ce n'est pas bien, même si vous ne vous souciez pas des lectures sales
Sam Saffron
La page vierge que vous obtenez lorsqu'une requête génère une exception pour laquelle vous n'avez pas implémenté de logique de nouvelle tentative. Que se passe-t-il sur vos sites lorsque l'exécution de la requête aboutit à une exception, avez-vous une logique de nouvelle tentative partout?
Sam Saffron le
Prenez une requête très bien optimisée dont vous savez qu'elle atteint les bons index. Ensuite, ajoutez des indices nolock et regardez-le devenir plus rapide. Si vous ne vous souciez pas des lectures sales, vous ne vous blesserez jamais en utilisant nolock.
Hardwareguy
13

Je doute que c'était un "gourou" qui avait eu une expérience dans le trafic élevé ...

Les sites Web sont généralement «sales» au moment où la personne consulte la page complètement chargée. Considérez un formulaire qui se charge à partir de la base de données, puis enregistre les données modifiées ?? C'est idiot la façon dont les gens disent que les lectures sales sont un non non.

Cela dit, si vous avez un certain nombre de couches qui s'appuient sur vos sélections, vous pourriez créer une redondance dangereuse. Si vous avez affaire à de l'argent ou des scénarios de statut, alors vous avez besoin non seulement de données transactionnelles en lecture / écriture, mais d'une solution de concurrence appropriée (ce que la plupart des «gourous» ne dérangent pas).

D'un autre côté, si vous avez une recherche avancée de produits pour un site Web (c'est-à-dire quelque chose qui ne sera probablement pas mis en cache et qui sera un peu intensif) et que vous avez déjà créé un site avec plus de quelques utilisateurs simultanés (phénominal combien "experts" ne l'ont pas fait), il est ridicule d'étouffer tous les autres processus derrière lui.

Sachez ce que cela signifie et utilisez-le le cas échéant. Votre base de données sera presque toujours votre principal goulot d'étranglement de nos jours et l'utilisation intelligente de NOLOCK peut vous faire économiser des milliers d'infrastructures.

EDIT: Ce n'est pas seulement les blocages que cela aide, c'est aussi à quel point vous allez faire attendre tout le monde jusqu'à ce que vous ayez terminé, ou vice versa.

Utilisation de NOLOCK Hint dans EF4?

Gats
la source
10

Aucune des réponses n'est fausse, mais peut-être un peu déroutante.

  • Lors de l'interrogation de valeurs / lignes uniques, il est toujours déconseillé d'utiliser NOLOCK - vous ne voudrez probablement jamais afficher des informations incorrectes ou peut-être même prendre des mesures sur des données incorrectes.
  • Lors de l'affichage d'informations statistiques approximatives, NOLOCK peut être très utile. Prenez SO comme exemple: il serait absurde de prendre des verrous pour lire le nombre exact de vues d'une question, ou le nombre exact de questions pour un tag. Personne ne se soucie si vous énoncez de manière incorrecte 3360 questions étiquetées avec "sql-server" maintenant, et à cause d'une annulation de transaction, 3359 questions une seconde plus tard.
realMarkusSchmidt
la source
Je ne suis pas du tout d'accord avec votre premier point. SI vous interrogez des valeurs / lignes uniques et que vous spécifiez un identifiant unique pour cette ligne et que vous savez qu'aucun autre processus n'y accédera, alors l'utilisation de nolock est parfaitement acceptable et réduit le blocage dans une application simultanée.
tuseau
1
Non ce n'est pas. La ligne peut changer pour d'autres raisons, par exemple l'insertion d'une autre ligne divise la page. Une indexation appropriée, un instantané de lecture validée et une isolation de l'instantané sont presque toujours de meilleures idées.
Mark Sowul
1
@tuseau si vous "savez" qu'aucun autre processus n'accédera à la ligne, le fait de prendre un verrou ne bloquera rien, donc ne vous coûtera (pratiquement) rien,
Andrew Hill
2

En tant que développeur professionnel, je dirais que cela dépend. Mais je suis définitivement les conseils de l'AGCS et de l'OMG Ponies. Sachez ce que vous faites, sachez quand cela aide et quand cela fait mal et

lire des astuces et autres mauvaises idées

ce qui pourrait vous faire comprendre le serveur SQL plus en profondeur. Je suis généralement la règle selon laquelle les conseils SQL sont MAUVAIS, mais malheureusement je les utilise de temps en temps quand j'en ai marre de forcer le serveur SQL à faire des choses ... Mais ce sont des cas rares.

Luke

Lucky Luke
la source
2

Lorsque le support d'application voulait répondre aux requêtes ad-hock du serveur de production à l'aide de SSMS (qui n'étaient pas pris en charge via les rapports), j'ai demandé qu'ils utilisent nolock. De cette façon, l'activité «principale» n'est pas affectée.

richard101
la source
2

Je suis d'accord avec certains commentaires sur l'indice NOLOCK et en particulier avec ceux qui disent "utilisez-le quand c'est approprié". Si l'application est mal écrite et utilise une méthode d'accès concurrentielle inappropriée, cela peut provoquer une escalade de verrouillage. Les tables hautement transactionnelles sont également verrouillées tout le temps en raison de leur nature. Avoir une bonne couverture d'index n'aidera pas à récupérer les données, mais définir ISOLATION LEVEL sur READ UNCOMMITTED le fait. Je crois également que l'utilisation de l'indice NOLOCK est sûre dans de nombreux cas lorsque la nature des changements est prévisible. Par exemple, dans la fabrication, lorsque les travaux avec les voyageurs passent par différents processus avec de nombreuses insertions de mesures, vous pouvez exécuter en toute sécurité une requête sur le travail terminé avec l'indicateur NOLOCK et ainsi éviter les collisions avec d'autres sessions qui mettent des verrous PROMOTIONNÉS ou EXCLUSIFS sur la table /page. Les données auxquelles vous accédez dans ce cas sont statiques, mais elles peuvent résider dans une table très transactionnelle avec des centaines de millions d'enregistrements et des milliers de mises à jour / insertions par minute. À votre santé

user2041151
la source
2

Je pense qu'il n'est pratiquement jamais correct d'utiliser nolock.

Si vous lisez une seule ligne, l'index correct signifie que vous n'aurez pas besoin de NOLOCK car les actions individuelles sur les lignes sont terminées rapidement.

Si vous lisez de nombreuses lignes pour autre chose qu'un affichage temporaire et que vous vous souciez de pouvoir répéter le résultat ou de vous défendre par le nombre produit, alors NOLOCK n'est pas approprié.

NOLOCK est une balise de substitution pour "je ne me soucie pas si cette réponse contient des lignes en double, des lignes qui sont supprimées ou des lignes qui n'ont jamais été insérées au départ en raison de la restauration"

Erreurs possibles sous NOLOCK:

  • Les lignes qui correspondent ne sont pas du tout renvoyées.
  • des lignes uniques sont renvoyées plusieurs fois (y compris plusieurs instances de la même clé primaire)
  • Les lignes qui ne correspondent pas sont renvoyées.

Toute action qui peut provoquer une division de page pendant l'exécution de la sélection noLock peut provoquer ces événements. Presque toutes les actions (même une suppression) peuvent provoquer un fractionnement de page.

Par conséquent: si vous «savez» que la ligne ne sera pas modifiée pendant que vous exécutez, n'utilisez pas nolock, car un index permettra une récupération efficace.

Si vous pensez que la ligne peut changer pendant l'exécution de la requête et que vous vous souciez de la précision, n'utilisez pas nolock.

Si vous envisagez NOLOCK en raison de blocages, examinez la structure du plan de requête pour des analyses de table inattendues, retracez les blocages et voyez pourquoi ils se produisent. NOLOCK autour des écritures peut signifier que les requêtes précédemment bloquées écriront potentiellement toutes les deux la mauvaise réponse.

Andrew Hill
la source
2

Les meilleures solutions, lorsque cela est possible, sont:

  • Répliquez vos données (à l'aide de la réplication de journaux) dans une base de données de rapports.
  • Utilisez des instantanés SAN et montez une version cohérente de la base de données
  • Utilisez une base de données qui a un meilleur niveau d'isolation de transaction fondamentale

Le niveau d'isolement de transaction SNAPSHOT a été créé car MS perdait des ventes au profit d'Oracle. Oracle utilise des journaux d'annulation / rétablissement pour éviter ce problème. Postgres utilise MVCC. À l'avenir, Heckaton de MS utilisera MVCC, mais il reste des années avant d'être prêt pour la production.

pwy
la source
Il y a une faute de frappe ci-dessus. Je veux dire "meilleur mécanisme fondamental d'isolement des transactions".
pwy
1
Le niveau d'isolement de transaction SNAPSHOT est une invention de MS. Fondamentalement, il met les données dans une table temporaire dans TEMPDB. Ce DB est partagé entre tous les DB de la boîte. Vous voudrez donc utiliser des SSD pour TEMPDB lorsque cela est possible. C'est probablement moins d'effort que les autres options.
pwy
1

NOLOCK est souvent exploité comme un moyen magique d'accélérer les lectures de bases de données, mais j'essaie d'éviter de l'utiliser autant que possible.

L'ensemble de résultats peut contenir des lignes qui n'ont pas encore été validées, qui sont souvent annulées ultérieurement.

Une erreur ou un ensemble de résultats peut être vide, contenir des lignes manquantes ou afficher la même ligne plusieurs fois.

En effet, d'autres transactions déplacent des données en même temps que vous les lisez.

READ COMMITTED ajoute un problème supplémentaire où les données sont corrompues dans une seule colonne où plusieurs utilisateurs modifient la même cellule simultanément.

WonderWorker
la source
-2

Dans la vraie vie où vous rencontrez des systèmes déjà écrits et que l'ajout d'index aux tables ralentit considérablement le chargement des données d'une table de données 14gig, vous êtes parfois obligé d'utiliser WITH NOLOCK sur vos rapports et de procéder à la fin du mois pour que les fonctions agrégées (somme , count, etc.) ne font pas de verrouillage de ligne, de page, de tableau et nuisent à la performance globale. Facile à dire dans un nouveau système, n'utilisez jamais WITH NOLOCK et utilisez des index - mais l'ajout d'index réduit considérablement le chargement des données, et quand on me dit, eh bien, modifiez la base de code pour supprimer les index, puis chargez en masse puis recréez les index - ce qui tout va bien si vous développez un nouveau système. Mais pas lorsque vous avez déjà un système en place.

user6699628
la source
1
que dites-vous
Max Alexander Hanna