web-dev-qa-db-fra.com

Qu'est-ce que "with (nolock)" dans SQL Server?

Quelqu'un peut-il expliquer les implications de l’utilisation de with (nolock) sur des requêtes, alors que vous ne devriez ou ne devriez pas l’utiliser?

Par exemple, si vous avez une application bancaire avec des taux de transaction élevés et beaucoup de données dans certaines tables, pour quels types de requêtes nolock serait-il acceptable? Y a-t-il des cas où vous devriez toujours l'utiliser/ne jamais l'utiliser?

567
Andy White

WITH (NOLOCK) équivaut à utiliser READ UNCOMMITED comme niveau d'isolation de transaction. Ainsi, vous courez le risque de lire une ligne non validée qui est par la suite restaurée, c'est-à-dire des données qui ne l'ont jamais été dans la base de données. Ainsi, bien que cela puisse éviter que les lectures soient bloquées par d'autres opérations, cela comporte un risque. Dans une application bancaire avec des taux de transaction élevés, ce ne sera probablement pas la bonne solution, quel que soit le problème que vous essayez de résoudre avec elle à mon humble avis.

428
David M

La question est ce qui est pire:

  • une impasse, ou
  • une mauvaise valeur?

Pour les bases de données financières, les blocages sont bien pires que les mauvaises valeurs. Je sais que ça sonne à l'envers, mais écoutez-moi. L'exemple traditionnel des transactions de base de données est la mise à jour de deux lignes, en soustrayant l'une et en ajoutant à une autre. C'est faux.

Dans une base de données financières, vous utilisez des transactions commerciales. Cela signifie ajouter une ligne à chaque compte. Il est de la plus haute importance que ces transactions soient terminées et que les lignes soient correctement écrites.

Obtenir le solde du compte temporairement incorrect n'est pas une grosse affaire, c'est à cela que sert le rapprochement de fin de journée. Et un découvert de compte est beaucoup plus susceptible de se produire parce que deux guichets automatiques sont utilisés à la fois plutôt qu’à cause d’une lecture non validée d’une base de données.

Cela dit, SQL Server 2005 a corrigé la plupart des problèmes qui rendaient NOLOCK nécessaire. Donc, à moins d'utiliser SQL Server 2000 ou une version antérieure, vous ne devriez pas en avoir besoin.

Lectures supplémentaires
Gestion des versions au niveau de la ligne

160
Jonathan Allen

L'exemple de manuel d'utilisation légitime de l'indicateur nolock est l'échantillonnage de rapports dans une base de données à mises à jour élevées OLTP.

Pour prendre un exemple d'actualité. Si une grande banque américaine souhaitait générer un rapport toutes les heures, recherchant les premiers signes d’un passage à l’échelle municipale, une requête nolock pourrait analyser les tables de transaction récapitulant les dépôts et retraits en espèces par ville. Pour un tel rapport, le faible pourcentage d'erreur provoqué par des transactions de mise à jour annulées ne réduirait pas la valeur du rapport.

52
saasman

Malheureusement, il ne s'agit pas seulement de lire des données non validées. En arrière-plan, vous risquez de lire deux fois les pages (dans le cas d'une division de page) ou de rater des pages. Donc, vos résultats peuvent être grossièrement asymétriques.

Départ article d'Itzik Ben-Gan . Voici un extrait:

"Avec l'indicateur NOLOCK (ou en définissant le niveau d'isolement de la session sur READ UNCOMMITTED), vous indiquez à SQL Server que vous ne vous attendez pas à une cohérence. Il n'y a donc aucune garantie. N'oubliez pas que" données incohérentes "ne signifie pas vous pouvez voir des modifications non validées qui ont ensuite été annulées ou des modifications de données dans un état intermédiaire de la transaction. Cela signifie également que, dans une simple requête qui analyse toutes les données de table/index, SQL Server peut perdre la position de balayage, ou vous pourriez finir par avoir deux fois la même ligne . "

52
sqlbelle

Vous ne savez pas pourquoi vous n'entendez pas les transactions financières dans les transactions de base de données (comme lorsque vous transférez des fonds d'un compte à un autre - vous ne commettez pas un côté de la transaction à la fois - c'est pourquoi les transactions explicites existent). Même si votre code est identique à celui des transactions commerciales, toutes les bases de données transactionnelles peuvent potentiellement effectuer des restaurations implicites en cas d'erreur ou d'échec. Je pense que cette discussion est bien au dessus de votre tête.

Si vous rencontrez des problèmes de verrouillage, implémentez le contrôle de version et nettoyez votre code.

Aucun verrou ne renvoie non seulement des valeurs erronées, mais également des enregistrements fantômes et des doublons.

Une idée fausse commune est que cela rend toujours les requêtes plus rapides. S'il n'y a pas de verrou en écriture sur une table, cela ne fait aucune différence. S'il y a des verrous sur la table, la requête peut être plus rapide, mais il y a une raison pour laquelle les verrous ont été inventés.

Pour être juste, voici deux scénarios spéciaux dans lesquels un indice nolock peut être utile

1) La base de données du serveur SQL antérieure à 2005 qui doit exécuter une requête longue sur la base de données live OLTP peut être le seul moyen

2) Une application mal écrite qui verrouille les enregistrements et rend le contrôle à l’UI, bloquant ainsi les lecteurs indéfiniment. Nolock peut être utile ici si l'application ne peut pas être corrigée (tierce partie, etc.) et si la base de données est antérieure à 2005 ou si la gestion des versions ne peut pas être activée.

30
Andrew

NOLOCK équivaut à READ UNCOMMITTED, mais Microsoft ne vous recommande pas de l'utiliser pour les instructions UPDATE ou DELETE:

Pour les instructions UPDATE ou DELETE: cette fonctionnalité sera supprimée dans une future version de Microsoft SQL Server. Évitez d'utiliser cette fonctionnalité dans les nouveaux travaux de développement et prévoyez de modifier les applications qui l'utilisent actuellement.

http://msdn.Microsoft.com/en-us/library/ms187373.aspx

Cet article s'applique à SQL Server 2005 et le support de NOLOCK existe donc si vous utilisez cette version. Afin de pérenniser votre code (en supposant que vous utilisiez des lectures modifiées), vous pouvez l’utiliser dans vos procédures stockées:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

23
Seibar

Vous pouvez l'utiliser lorsque vous ne faites que lire des données, sans vous soucier de savoir si vous récupérez ou non des données qui ne sont pas encore validées.

Cela peut être plus rapide en lecture, mais je ne peux pas vraiment dire de combien.

En général, je déconseille de l'utiliser - la lecture de données non validées peut être un peu déroutante.

19
marc_s

Une autre base de données de rapports est généralement satisfaisante, les données sont peut-être déjà anciennes et les écritures ne se produisent pas. Dans ce cas, toutefois, l'option doit être définie au niveau de la base de données ou de la table par l'administrateur en modifiant le niveau d'isolation par défaut.

Dans le cas général: vous pouvez l'utiliser quand vous êtes très sûr que vous pouvez lire des données anciennes. La chose importante à retenir est que sa très facile de se tromper. Par exemple, même si tout va bien au moment où vous écrivez la requête, êtes-vous sûr que quelque chose ne changera pas dans la base de données à l'avenir pour rendre ces mises à jour plus importantes?

J'ajouterai également que je pense que c'est probablement non une bonne idée dans l'application bancaire. Ou l'inventaire app. Ou partout où vous songez aux transactions.

17
Joel Coehoorn

Réponse simple - chaque fois que votre code SQL ne modifie pas les données et que vous avez une requête susceptible d'interférer avec une autre activité (via le verrouillage).

Il convient de prendre en compte toutes les requêtes utilisées pour les rapports, en particulier si la requête prend plus d'une seconde, par exemple.

Cela est particulièrement utile si vous avez des rapports de type OLAP que vous exécutez avec une base de données OLTP.

La première question à poser, cependant, est "pourquoi suis-je inquiet à ce sujet?" Selon mon expérience, le comportement de verrouillage par défaut a souvent lieu lorsque quelqu'un est en mode "rien d'essayer", ce qui est un cas où des conséquences inattendues ne sont pas improbables. Trop souvent, il s’agit d’une optimisation prématurée et peut être trop facilement intégrée à une application "au cas où". Il est important de comprendre pourquoi vous le faites, quel problème il résout et si vous avez réellement le problème.

14
dkretz

Mes 2 centimes - il est logique d'utiliser WITH (NOLOCK) lorsque vous devez générer des rapports. À ce stade, les données ne changeraient pas beaucoup et vous ne voudriez pas verrouiller ces enregistrements.

9
SoftwareGeek

Si vous gérez des transactions financières, vous ne voudrez plus jamais utiliser nolock. nolock est le mieux utilisé pour sélectionner des tables volumineuses comportant de nombreuses mises à jour et vous ne vous inquiétez pas de savoir si l'enregistrement que vous obtenez risque d'être obsolète.

Pour les enregistrements financiers (et presque tous les autres enregistrements dans la plupart des applications), nolock causerait des dégâts, car vous pourriez potentiellement relire des données à partir d'un enregistrement en cours d'écriture sans obtenir les données correctes.

8
Andrew Hare

Réponse courte:

Ne jamais utiliser WITH (NOLOCK).

Réponse longue:

NOLOCK est souvent utilisé 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 ultérieurement restaurées.

Une erreur ou un jeu de résultats peut être vide, être 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 dans lequel les données sont corrompues dans une seule colonne lorsque plusieurs utilisateurs changent simultanément la même cellule.

Il y a également d'autres effets secondaires, qui ont pour conséquence de sacrifier l'augmentation de vitesse que vous espériez gagner en premier lieu.

On peut soutenir qu'il est acceptable de l'utiliser dans des endroits où vous pouvez vous en sortir, mais à quoi ça sert? Je ne peux penser à aucune situation dans laquelle des données corrompues sont acceptables.

Ne jamais utiliser NOLOCK jamais.

(déjà)

7
Knickerless-Noggins

J'avais l'habitude de récupérer un "prochain lot" pour les choses à faire. Peu importe dans ce cas quel élément exact, et de nombreux utilisateurs exécutent cette même requête.

7
Otávio Décio

Utilisez nolock lorsque vous êtes d'accord avec les données "sales". Ce qui signifie que nolock peut également lire des données en cours de modification et/ou des données non validées.

Ce n'est généralement pas une bonne idée de l'utiliser dans un environnement de transaction élevée et c'est pourquoi ce n'est pas une option par défaut pour une requête.

6
Learning

J'utilise avec (nolock) un indice, en particulier dans les bases de données SQLServer 2000 avec une activité élevée. Je ne suis cependant pas certain que cela soit nécessaire dans SQL Server 2005. J'ai récemment ajouté cet indice dans un SQL Server 2000 à la demande du DBA du client, car il remarquait beaucoup de verrous SPID.

Tout ce que je peux dire, c'est que l'utilisation de l'indication ne nous a PAS fait mal et semble avoir résolu le problème de verrouillage. Le DBA de ce client particulier a essentiellement insisté pour que nous utilisions l'indication.

En passant, les bases de données avec lesquelles je traite sont des systèmes d’alternative aux systèmes de réclamations des entreprises, nous parlons donc de millions d’enregistrements et de plus de 20 tables dans de nombreuses jointures. J'ajoute généralement un indicateur WITH (nolock) pour chaque table de la jointure (sauf s'il s'agit d'un tableau dérivé, auquel cas vous ne pouvez pas utiliser cet indicateur particulier).

6
user52212

La réponse la plus simple est une question simple: avez-vous besoin que vos résultats soient reproductibles? Si oui, alors NOLOCKS ne convient en aucun cas

Si vous n'avez pas besoin de répétabilité, alors nolocks peut être utile, en particulier si vous n'avez pas le contrôle sur tous les processus se connectant à la base de données cible.

4
Ed Green