Pourquoi utiliser un niveau d'isolement READ UNCOMMITTED?


225

En termes simples, quels sont les inconvénients et les avantages de l'utilisation

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

dans une requête pour les applications .NET et les applications de services de reporting?

Réponses:


210

Ce niveau d'isolement permet des lectures sales. Une transaction peut voir des modifications non validées apportées par une autre transaction.

Pour maintenir le plus haut niveau d'isolement, un SGBD acquiert généralement des verrous sur les données, ce qui peut entraîner une perte de simultanéité et une surcharge de verrouillage élevée. Ce niveau d'isolement détend cette propriété.

Vous voudrez peut-être consulter l'article Wikipedia surREAD UNCOMMITTED pour quelques exemples et une lecture plus approfondie.


Vous pouvez également consulter l' article de blog de Jeff Atwood sur la manière dont lui et son équipe ont résolu un problème de blocage dans les premiers jours de Stack Overflow. Selon Jeff:

Mais est-ce nolockdangereux? Pourriez-vous finir par lire des données invalides avec read uncommittedON? Oui, en théorie. Vous ne manquerez pas d'astronautes d'architecture de base de données qui commencent à vous abandonner la science ACID et tout sauf à déclencher l'alarme incendie du bâtiment lorsque vous leur dites que vous voulez essayer nolock. C'est vrai: la théorie fait peur. Mais voici ce que je pense: "En théorie, il n'y a pas de différence entre la théorie et la pratique. En pratique, il y en a."

Je ne recommanderais jamais d'utiliser nolock comme correctif général de l'huile de serpent "bon pour ce qui vous fait mal" pour tous les problèmes de blocage de base de données que vous pourriez avoir. Vous devez d'abord essayer de diagnostiquer la source du problème.

Mais dans la pratique, l'ajout nolockde requêtes que vous connaissez absolument sont des affaires simples et directes en lecture seule ne semblent jamais poser de problèmes ... Tant que vous savez ce que vous faites.

Une alternative au READ UNCOMMITTEDniveau que vous voudrez peut-être considérer est le READ COMMITTED SNAPSHOT. Citant encore Jeff:

Les instantanés reposent sur une toute nouvelle méthode de suivi des modifications de données ... plus qu'une simple modification logique, cela nécessite que le serveur gère les données physiquement différemment. Une fois cette nouvelle méthode de suivi des modifications de données activée, elle crée une copie ou un instantané de chaque modification de données. En lisant ces instantanés plutôt que des données en direct en cas de conflit, les verrous partagés ne sont plus nécessaires lors des lectures et les performances globales de la base de données peuvent augmenter.


13
L'auteur semble impliquer que la lecture non validée / aucun verrou ne retournera les dernières données validées. D'après ce que je comprends, la lecture non validée retournera la dernière valeur définie, même à partir de transactions non validées. Si tel est le cas, le résultat ne serait pas de récupérer les données "quelques secondes obsolètes". Ce serait (ou du moins pourrait si la transaction qui a écrit les données que vous lisez est annulée) récupérer des données qui n'existent pas ou qui n'ont jamais été validées. Suis-je trompé?
xr280xr

4
Très bonne réponse. BTW, Oracle a un «instantané» par défaut depuis que je le connais, probablement des décennies avant que Sql Server ne le présente. J'ai été assez déçu lorsque j'ai commencé avec SQL Server et j'ai découvert que tous les problèmes de concurrence ont été résolus en utilisant des mécanismes de verrouillage "primitifs". Jamais vu "Lire sans engagement" dans Oracle. Et le pratiquant est aussi heureux que les astronautes.
Stefan Steinegger

13
READ UNCOMMITTEDpeut également vous faire lire deux fois des lignes ou manquer des lignes entières . Si un fractionnement de page se produit pendant que vous lisez, vous pouvez manquer des morceaux entiers de données. WITH(NOLOCK)ne doit être utilisé que si la précision des résultats n'est pas importante
Ian Boyd

8
@DanielNolan, Recommander cet article est dangereux parce que Jeff ne savait pas ce qu'il faisait . La lecture non validée n'a de sens que pour la lecture des données qui ne seront jamais modifiées. Essayer de l'utiliser pour lire des tableaux qui seraient écrits signifie que vous lirez en pratique quelque chose qui sera annulé. Ce n'est pas seulement que vous lisez des données qui datent de quelques secondes, mais vous .................................. ................... ‌ ‌ ........................... ....
Pacerier

5
................................... sont en train de lire des données qui ne sont même jamais engagées. C'est la définition même des lectures corrompues. Et si vous allez écrire sur la base des résultats de ces lectures non validées, vous écrirez en pratique des données corrompues. L'article a également déclaré que "MySQL, qui a grandi sur les applications Web, est beaucoup moins pessimiste que SQL Server". Ce n'est pas vrai, Sql Server fonctionne par défaut au niveau de lecture validée, tandis que MySQL fonctionne aux lectures répétables par défaut, à cinq niveaux de lecture non validée .
Pacerier

36

Cela peut être utile pour voir la progression des longues requêtes d'insertion, faire des estimations approximatives (similaires COUNT(*)ou approximatives SUM(*)), etc.

En d'autres termes, les résultats renvoyés par les requêtes de lecture sale sont corrects tant que vous les traitez comme des estimations et ne prenez aucune décision critique en fonction de celles-ci.


36

Mon cas d'utilisation préféré read uncommitedest de déboguer quelque chose qui se passe dans une transaction.

Démarrez votre logiciel sous un débogueur, pendant que vous parcourez les lignes de code, il ouvre une transaction et modifie votre base de données. Pendant que le code est arrêté, vous pouvez ouvrir un analyseur de requêtes, définir le niveau d'isolement non engagé en lecture et effectuer des requêtes pour voir ce qui se passe.

Vous pouvez également l'utiliser pour voir si les procédures longues sont bloquées ou mettre à jour correctement votre base de données.

C'est formidable si votre entreprise aime créer des procédures stockées trop complexes.


6
Mon entreprise aime créer des procédures stockées trop complexes. Quelle bonne idée pour le dépannage!
Brandon

22

L'avantage est qu'il peut être plus rapide dans certaines situations. L'inconvénient est que le résultat peut être erroné (les données qui n'ont pas encore été validées pourraient être retournées) et il n'y a aucune garantie que le résultat soit reproductible.

Si vous vous souciez de la précision, ne l'utilisez pas.

Plus d'informations sur MSDN :

Implémente un verrouillage de lecture sale ou d'isolement de niveau 0, ce qui signifie qu'aucun verrou partagé n'est émis et aucun verrou exclusif n'est respecté. Lorsque cette option est définie, il est possible de lire des données non validées ou sales; les valeurs des données peuvent être modifiées et des lignes peuvent apparaître ou disparaître dans l'ensemble de données avant la fin de la transaction. Cette option a le même effet que la définition de NOLOCK sur toutes les tables de toutes les instructions SELECT d'une transaction. C'est le moins restrictif des quatre niveaux d'isolement.


Comment cela affecterait-il la vitesse de la requête?
Kip Real

11
@Kip - les selectinstructions n'auraient pas à attendre pour acquérir des verrous partagés sur des ressources qui sont exclusivement verrouillées par d'autres transactions.
Jarrod Dixon

15

Quand est-il autorisé à utiliser READ UNCOMMITTED?

Règle générale

Bon : grands rapports agrégés montrant des totaux en constante évolution.

Risqué : Presque tout le reste.

Les bonnes nouvelles sont que la majorité des rapports de lecture seule dans cette chute Bonne catégorie.

Plus de détails...

Ok pour l'utiliser:

  • Presque tous les rapports agrégés accessibles aux utilisateurs pour les données actuelles et non statiques, par exemple les ventes depuis le début de l'année. Il risque une marge d'erreur (peut-être <0,1%) qui est beaucoup plus faible que d'autres facteurs d'incertitude tels que la saisie d'une erreur ou simplement le caractère aléatoire du moment où les données sont enregistrées minute par minute.

Cela couvre probablement la majorité de ce qu'un service de Business Intelligence ferait dans, disons, SSRS. L'exception, bien sûr, est tout ce qui a des signes $ devant. De nombreuses personnes représentent de l'argent avec beaucoup plus de zèle qu'appliqué aux mesures de base connexes nécessaires pour servir le client et générer cet argent. (Je blâme les comptables).

Lorsque risqué

  • Tout rapport qui descend au niveau de détail. Si ce détail est requis, cela implique généralement que chaque ligne sera pertinente pour une décision. En fait, si vous ne pouvez pas extraire un petit sous-ensemble sans le bloquer, c'est peut-être pour la bonne raison qu'il est en cours de modification.

  • Données historiques. Cela fait rarement une différence pratique, mais bien que les utilisateurs comprennent que les données en constante évolution ne peuvent pas être parfaites, ils ne pensent pas la même chose des données statiques. Les lectures sales ne feront pas de mal ici, mais les doubles lectures peuvent parfois l'être. Étant donné que vous ne devriez pas avoir de blocs sur les données statiques de toute façon, pourquoi les risquer?

  • Presque tout ce qui alimente une application qui a également des capacités d'écriture.

Quand même le scénario OK n'est pas OK.

  • Existe-t-il des applications ou des processus de mise à jour utilisant de grosses transactions uniques? Ceux qui suppriment puis réinsèrent un grand nombre d'enregistrements dont vous faites état? Dans ce cas, vous ne pouvez vraiment rien utiliser NOLOCKsur ces tables.

Bon point sur les rapports. En fait, la première idée qui m'est venue à l'esprit était de savoir si je devais utiliser read uncommitteddes applications Web lorsque l'utilisateur voit une grille d'interface utilisateur où la précision des données n'est pas si importante. L'utilisateur veut juste un aperçu rapide des enregistrements qui pourraient y être, et peut-être avec un peu de pagination, de tri et de filtrage. Uniquement lorsque l'utilisateur clique sur le bouton Modifier, j'essaie de lire l'enregistrement le plus récent avec un niveau d'isolement plus strict. Une telle approche ne devrait-elle pas être meilleure en termes de performances?
JustAMartin

Oui, je pense que c'est raisonnable. N'oubliez pas que le problème le plus important consiste à s'assurer que les données n'ont pas été modifiées par quelqu'un d'autre entre le moment où vous appuyez sur le bouton Modifier et le moment de la soumission. Vous pouvez gérer cela en démarrant une transaction récupérant les données comme select item from things with (UPDLOCK). Mettez un délai d'attente rapide afin que s'il ne peut pas acquérir le verrou rapidement, il indique à l'utilisateur qu'il est en cours de modification. Cela vous protégera non seulement des utilisateurs mais des développeurs. Le seul problème ici est que vous devez commencer à réfléchir aux délais d'attente et à la façon dont vous gérez cela dans l'interface utilisateur.
Adamantish

6

En ce qui concerne la création de rapports, nous l'utilisons dans toutes nos requêtes de création de rapports pour éviter qu'une requête ne bloque les bases de données. Nous pouvons le faire parce que nous tirons des données historiques, pas des données à la microseconde près.


4

Utilisez READ_UNCOMMITTED dans une situation où la source est peu susceptible de changer.

  • Lors de la lecture des données historiques. par exemple, certains journaux de déploiement qui se sont produits il y a deux jours.
  • Lors de la relecture des métadonnées. par exemple application basée sur les métadonnées.

N'utilisez pas READ_UNCOMMITTED lorsque vous savez que la souce peut changer pendant l'opération de récupération.


1
Je pense que c'est l'inverse qui s'applique. Tout d'abord, les données statiques doivent être lues correctement sans blocs. Si elle ne bloque alors vous avez maintenant découvert il y a un important problème de transaction de suspension à corriger. Les utilisateurs s'attendent également à ce que cela corresponde à la dernière décimale qu'ils aient imprimée pour le rapport annuel de l'année dernière. Ils ne s'attendent généralement pas à ce que les rapports qu'ils connaissent sont en constante évolution. Cela ne vaut pas pour les rapports détaillés, extrêmement sensibles au facteur temps ou financiers, mais si 1 erreur de saisie sur 1000 est tolérable, il en est de même READ UNCOMMITTED.
Adamantish

TLDR: Si les données ne changent pas, vous n'avez pas besoin de LIRE UNCOMMITTED car il n'y a aucun bloc de toute façon. Si vous vous trompez et que cela change, c'est une bonne chose que vous ayez empêché les utilisateurs d'obtenir des données plus sales que prévu.
Adamantish

Oui, j'ai tendance à être d'accord avec @Adamantish ici - vous pouvez profiter de la READ UNCOMMITTEDplupart des situations dans lesquelles vos données sont activement utilisées et vous souhaitez réduire la charge sur le serveur pour éviter d'éventuels blocages et annulations de transactions simplement parce que certains utilisateurs abusent négligemment " Actualiser "dans une page Web avec une grille de données. Les utilisateurs qui consultent un tas d'enregistrements en même temps, ne se soucient généralement pas beaucoup si les données sont un peu obsolètes ou partiellement mises à jour. Ce n'est que lorsqu'un utilisateur est sur le point de modifier un enregistrement que vous voudrez peut-être lui fournir les données les plus précises.
JustAMartin

2

Cela vous donnera des lectures sales et vous montrera des transactions qui ne sont pas encore validées. Telle est la réponse la plus évidente. Je ne pense pas que ce soit une bonne idée de l'utiliser uniquement pour accélérer vos lectures. Il existe d'autres façons de le faire si vous utilisez une bonne conception de base de données.

Il est également intéressant de noter ce qui ne se passe pas. READ UNCOMMITTED n'ignore pas seulement les autres verrous de table. Cela ne cause pas non plus de verrous en soi.

Imaginez que vous générez un rapport volumineux ou que vous migrez des données hors de votre base de données à l'aide d'une instruction SELECT volumineuse et éventuellement complexe. Cela entraînera un verrou partagé qui peut être transformé en verrou de table partagé pour la durée de votre transaction. D'autres transactions peuvent être lues dans le tableau, mais les mises à jour sont impossibles. Cela peut être une mauvaise idée s'il s'agit d'une base de données de production car la production peut s'arrêter complètement.

Si vous utilisez READ UNCOMMITTED, vous ne définirez pas de verrou partagé sur la table. Vous pouvez obtenir le résultat de certaines nouvelles transactions ou vous ne pouvez pas en fonction de l'endroit où la table dans laquelle les données ont été insérées et de la durée de lecture de votre transaction SELECT. Vous pouvez également obtenir les mêmes données deux fois si, par exemple, un fractionnement de page se produit (les données seront copiées vers un autre emplacement dans le fichier de données).

Donc, si c'est très important pour vous que des données puissent être insérées pendant votre SELECT, READ UNCOMMITTED peut avoir du sens. Vous devez considérer que votre rapport peut contenir des erreurs, mais s'il est basé sur des millions de lignes et que seules quelques-unes sont mises à jour lors de la sélection du résultat, cela peut être "assez bon". Votre transaction peut également échouer tous ensemble, car l'unicité d'une ligne peut ne pas être garantie.

Un meilleur moyen peut être d'utiliser le NIVEAU D'ISOLEMENT D'INSTANTANÉ, mais vos applications peuvent avoir besoin de quelques ajustements pour l'utiliser. Un exemple de cela est si votre application prend un verrou exclusif sur une ligne pour empêcher les autres de le lire et de passer en mode édition dans l'interface utilisateur. LE NIVEAU D'ISOLEMENT D'INSTALLATION s'accompagne également d'une pénalité de performance considérable (en particulier sur le disque). Mais vous pouvez surmonter cela en jetant du matériel sur le problème. :)

Vous pouvez également envisager de restaurer une sauvegarde de la base de données à utiliser pour générer des rapports ou charger des données dans un entrepôt de données.


0

Il peut être utilisé pour une table simple, par exemple dans une table d'audit d'insertion uniquement, où il n'y a pas de mise à jour de la ligne existante et pas de fk vers une autre table. L'insert est un simple insert qui n'a pas ou peu de chances de revenir en arrière.


-7

J'utilise toujours READ UNCOMMITTED maintenant. C'est rapide avec le moins de problèmes. Lorsque vous utilisez d'autres isolations, vous rencontrerez presque toujours des problèmes de blocage.

Tant que vous utilisez les champs d'incrémentation automatique et que vous prêtez un peu plus d'attention aux insertions que votre amende, et vous pouvez dire adieu aux problèmes de blocage.

Vous pouvez faire des erreurs avec READ UNCOMMITED mais pour être honnête, il est très facile de vous assurer que vos inserts sont à l'épreuve. Les insertions / mises à jour qui utilisent les résultats d'une sélection sont la seule chose à surveiller. (Utilisez READ COMMITTED ici, ou assurez-vous que les lectures incorrectes ne causeront pas de problème)

Allez donc les Dirty Reads (spécialement pour les gros rapports), votre logiciel fonctionnera plus facilement ...


6
Ceci est très imprécis et ne touche que la surface des problèmes qui peuvent survenir avec nolock. Les pages peuvent se diviser, les jointures peuvent échouer, vous pouvez lire des données inexistantes ou dupliquer des données. Il n'y a aucun moyen de rendre son utilisation à toute épreuve: vous ne pouvez pas faire confiance à la précision de quoi que ce soit sous ce niveau d'isolement. LIRE L'INSTANTANÉ ENGAGÉ est une "fausse panacée" moins dangereuse
Mark Sowul

@MarkSowul Le vote négatif de cette réponse me semble injuste. @Clive était clair qu'il passerait aux Committedinsertions et mises à jour. En ce qui concerne les autres problèmes, il a également démontré sa conscience des problèmes de partage de page en mentionnant l'utilisation d'une clé d'incrémentation automatique. Je suis d'accord avec lui que presque tous les reportages en direct faits pour être lus par un simple humain peuvent tolérer de légères différences dans la décimale finale. Je suis d'accord que c'est une autre histoire pour les listes détaillées ou les données destinées à être lues et transformées par machine, tout comme Clive.
Adamantish

1
Ce commentaire démontre également un manque de compréhension complète des problèmes possibles liés au nolock. "De légères différences dans la décimale finale" le couvrent à peine. Même toucher à «utiliser uniquement la lecture engagée pour les insertions / mises à jour» est faux comme conseil général (que faire si c'est «insérer un enregistrement s'il n'existe pas»?). En tout état de cause, "[lire sans engagement] est rapide avec le moins de problèmes" est catégoriquement faux.
Mark Sowul

Pour mémoire, je suis d'accord avec votre réponse, Adamantish: agrégations à peu près exactes et rien d'autre.
Mark Sowul
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.