NOLOCK(SQL Serverヒント)は悪い習慣ですか?


125

私はウェブサイトやアプリケーションではないビジネスをしているミッションクリティカル ->例。バンキングソフトウェア、宇宙飛行、集中治療モニタリングアプリケーションなど。

それで、その大きな免責事項で、いくつかのSqlステートメントでNOLOCKヒントを使用するのは悪いことですか?何年も前に、仲間のSQL管理者から、「ダーティリード」に満足している場合はNOLOCKを使用するように勧められました。テーブル/行/何でも。

また、デッドロックが発生している場合は、これが優れたソリューションであるとも言われました。したがって、SQLグルがいくつかのランダムコードを手伝ってくれて、SQLコードのすべてのNOLOCKSに気付くまで、私は数年にわたってその考えに従いました。私は丁寧に叱られました、そして彼はそれを私に説明しようとしました(なぜそれが良いことではないのですか)そして私はちょっと迷いました。彼の説明の本質は「それはより深刻な問題に対するバンドエイドの解決策だと感じました。特にデッドロックが発生している場合は。そのため、問題の根本を修正してください。

私はそれについて最近グーグルをして、この投稿に出くわしました

それで、いくつかのSQL DBの達人先生が私を啓発してくれますか?


わかりません、サム、よく読んでいるWebサイトの場合は、スナップショット分離を使用すると言っています。しかし、それであなたはSOがそれをしたと言っています、そしてそれは悪いですか?または単にNOLOCKを使用しますか?
Pure.Krome 2009

回答:


67

NOLOCKヒントを使用すると、SELECTステートメントのトランザクション分離レベルはREAD UNCOMMITTEDます。つまり、クエリではダーティで一貫性のないデータが表示される可能性があります。

これは原則として適用することをお勧めしません。このダーティリード動作がミッションクリティカルなWebベースのアプリケーションで問題ない場合でも、NOLOCKスキャンにより601エラーが発生し、ロック保護の欠如の結果としてデータの移動が原因でクエリが終了する可能性があります。

スナップショット分離が役立つ場合と害を及ぼす場合を読むことをお勧めします-MSDNでは、ほとんどの状況でSNAPSHOTではなくREAD COMMITTED SNAPSHOTを使用することを推奨しています。


1
レックス、スナップショットの分離に関するメモを追加してください。
サムサフラン

2
ええ、サムはスナップショット分離を言っており、コミットされたスナップショットの読み取りを提案しています。私はとても混乱しています:P(そして私はまだ記事を掘り下げていません!)
Pure.Krome

2
たまに役立ちますが、通常はプロダクションには役立ちません。私は、テストするデータのサンプルを引き出すために、またはダーティリードが問題にならない大まかな桁数を主に気にするレポートの生成に頻繁に使用します。
TimothyAWiseman、2012年

NOLOCK ==コミットされた行が欠落していても、コミットされていない行が含まれているかどうかは気にしません。まれに、同じ行が複数回返され、非常にまれに、クエリに一致しない行が返されます。(blogs.msdn.com/b/sqlcat/archive/2007/02/01/を参照、このトピックに関する別のSO q'nから発見)
Andrew Hill

106

Stack Overflowに取り組む前、私はNOLOCKあなたが潜在的にSELECTwith NOLOCKを実行し、古くなっているか、一貫性のないデータで結果を返す可能性があるという原則に反対しました。考慮すべき要素は、別のプロセスが同じテーブルからデータを選択しているときに、同時にいくつのレコードを挿入/更新できるかです。これが頻繁に発生する場合は、などのデータベースモードを使用しない限り、デッドロックの可能性が高くなりますREAD COMMITED SNAPSHOT

NOLOCKその後SELECT、大量にロードされたSQL Serverのデッドロックを排除するだけでなく、パフォーマンスを向上させる方法を確認した後の使用についての見方を変えました。データが100%コミットされていないことを気にせず、古くてもすぐに結果を返す必要がある場合があります。

使用することを考えているときは、自分に質問してくださいNOLOCK

クエリにはINSERT/ UPDATEコマンドの数が多いテーブルが含まれていますか?また、クエリから返されたデータに特定の瞬間にこれらの変更がない可能性があるかどうかを気にしますか?

答えがいいえの場合は、 NOLOCKパフォーマンスを改善するためにします。


NOLOCKStack Overflowのコードベース内でキーワードの クイック検索を実行したところ、138のインスタンスが見つかったので、かなり多くの場所で使用しました。


7
IMO、これは少し単純化しています。デッドロックは、カバードインデックスを使用して、クラスター化インデックスからプレッシャーを取り除くことで削除できます。
ミッチウィート

8
インデックスカバレッジの重要性を減らすつもりはありません。NOLOCKを使用するクエリは、挿入/更新の数が多いテーブルのインデックスによって実現される利点に加えて、パフォーマンスを向上させることができます。Stack Overflowでのクエリ速度は、データが不正確または欠落している場合でも最優先されます。
ジェフダルガス

9
どうやらを使用して重複行取得できますNOLOCK。これは、私があなたの答えに反対票を投じなければならないことを意味します。ごめんなさい。
ErikE

1
@MitchWheat A SELECTは、カバリングインデックスからのみ読み取るため、デッドロックを引き起こす可能性があります。SPID 1)SELECTをカバーするインデックスから開始します。SPID 2)UPDATEテーブルの開始。次に、更新はカバリングインデックスの更新に移ります。UPDATEによってロックされたインデックス範囲に達し、SELECTブロックされます。SPID 1)はまだカバリングインデックスをシークし、によってロックされている範囲を見つけてUPDATEブロックされます。デッドロック。そのデッドロックを解決できるものはありません(SQL Serverエラー1205をキャッチし、自動的に再試行するか、またはを使用する場合を除くNOLOCK
Ian Boyd

2
この回答について注意すべき重要なことは、それが当面の問題に適切であったということです。アプリケーションによっては、データが古くなったり、コミットされていなかったり、重複したり、失われたりするリスクは、トレードオフに値しない場合があります。
ホリスティック開発者

20

ダーティリードを気にしない場合(主にREADの状況)、問題ありませんNOLOCK

ただし、ロックの問題の大部分は、クエリのワークロードに「正しい」インデックスがないことが原因であることに注意してください(ハードウェアがタスクに依存していると想定)。

そしてグルの説明は正しかった。これは通常、より深刻な問題に対する応急処置の解決策です。

編集:私は、NOLOCKを使用するように提案しているわけではありません。私はそれを明らかに明確にすべきだったと思います。(私はそれを大丈夫だと分析した極端な状況では、これを使用するだけです)。例として、しばらく前に、ロックの問題を解決するためにNOLOCKを散りばめたTSQLに取り組みました。私はそれらをすべて削除し、正しいインデックスを実装し、すべてのデッドロックがなくなりました。


3
うーん..まだわかりません。だからそれは結構ですが、それは貧弱な形でもあります..それはあなたが言っていることですか?
Pure.Krome 2009

ダーティーリードを気にしないことを前提にすると、害はありません。しかし、それは通常、症状を治療するケースであり、原因ではありません...
ミッチウィート

2
まあ、私はその公平なrexemが単に反対投票されたとは思いません、私はあなたがnolockを使用したときに浮かぶ任意のエラーに対処しなかったと思います。あなたのウェブサイトでたまに空白のエラーページを表示することは問題ありません、それは本当に貧弱なフォームです。「ダーティリードを気にしないと問題ない」という主張は嫌いです...ダーティリードを気にしなくても問題ありません
Sam Saffron

クエリが、再試行ロジックを実装していない例外を生成したときに表示される空白のページ。クエリの実行結果が例外である場合、サイトで何が起こりますか?あらゆる場所に再試行ロジックがありますか?
サムサフラン

適切なインデックスにアクセスしていることがわかっている、非常によく最適化されたクエリを実行します。次に、nolockヒントを追加し、それが速くなるのを観察します。ダーティリードを気にしない場合は、nolockを使用しても害はありません。
Hardwareguy

13

疑わしいのは、高トラフィックでの経験があった「達人」だった...

通常、ユーザーが完全に読み込まれたページを表示しているときには、Webサイトは「ダーティ」です。データベースからロードし、編集したデータを保存するフォームを考えてみますか?ダーティリードがこのようなノーノーであることについて人々が続ける方法はばかげています。

とは言っても、selectに多数のレイヤーを構築している場合、危険な冗長性を構築している可能性があります。お金やステータスのシナリオを扱っている場合は、トランザクションデータの読み取り/書き込みだけでなく、適切な同時実行ソリューション(ほとんどの「教祖」が気にしないもの)が必要です。

一方、Webサイトの高度な製品検索(つまり、キャッシュされずに少し集中する可能性があるもの)があり、数人を超える同時ユーザー(名目上の数)でサイトを構築したことがある場合「専門家」はそうではありません)、それの背後にある他のすべてのプロセスをボトルネックにすることはばかげています。

それが何を意味するかを理解し、適切なときにそれを使用してください。最近のデータベースはほとんど常に主要なボトルネックになり、NOLOCKの使用を賢くすることでインフラストラクチャを何千も節約できます。

編集:それはそれが役立つデッドロックだけではなく、あなたがどれだけ他の人にあなたが終わるまで待つか、またはその逆です。

EF4でNOLOCKヒントを使用していますか?


10

答えはどれも間違っていませんが、少し混乱するかもしれません。

  • 単一の値/行をクエリする場合、NOLOCKを使用することは常に悪い習慣です。おそらく、誤った情報を表示したり、誤ったデータに対してなんらかのアクションを実行したりすることはおそらくありません。
  • 大まかな統計情報を表示する場合、NOLOCKは非常に役立ちます。例として、SO取る:読むためにロックを取ることはナンセンスだろう正確な質問のビューの数、またはタグのための質問の正確な数を。「sql-server」でタグ付けされた3360の質問を誤って述べても、トランザクションのロールバックのために、1秒後に3359の質問が出されても、誰も気にしません。

私はあなたの最初の点にまったく同意しません。単一の値/行をクエリしていて、その行に一意のIDを指定していて、他のプロセスがその行にアクセスしないことがわかっている場合、nolockの使用は完全に受け入れられ、同時実行アプリケーションでのブロックを減らします。
tuseau

1
いいえ、ちがいます。他の理由で行が変更される場合があります。たとえば、別の行を挿入するとページが分割されます。適切なインデックス作成、コミットされたスナップショットの読み取り、スナップショットの分離は、ほとんどの場合、優れたアイデアです。
Mark Sowul 2012

1
@tuseau他のプロセスが行にアクセスしないことを「知っている」場合、ロックを取得する動作は何もブロックしないため、(実際には)何もかかりません
Andrew Hill

2

プロの開発者として、私はそれが依存すると思います。しかし、私は間違いなくGATSとOMGポニーのアドバイスに従います。あなたが何をしているかを知り、それがいつ役立つか、いつ痛いかを知る

ヒントやその他の貧弱なアイデアを読む

SQLサーバーをより深く理解できるようになる理由 私は通常、SQLヒントは悪であるという規則に従いますが、残念ながらSQLサーバーを強制的に使用することにうんざりすると、時々それらを使用します...しかし、これらはまれなケースです。

ルーク


2

app-supportがSSMSを使用して本番サーバーからのアドホッククエリに応答したい場合(レポート経由で提供されなかった)、私はnolockを使用するように要求しました。そうすれば、「主要な」ビジネスは影響を受けません。


2

NOLOCKヒントについてのいくつかのコメント、特に「適切なときに使用する」というコメントに同意します。アプリケーションの記述が不十分で、並行性が不適切な方法で使用されている場合–ロックのエスカレーションが発生する可能性があります。トランザクションの多いテーブルも、その性質上、常にロックされています。インデックスカバレッジが適切であっても、データの取得には役立ちませんが、ISOLATION LEVELをREAD UNCOMMITTEDに設定すると効果があります。また、変更の性質が予測可能な場合、NOLOCKヒントの使用は多くの場合安全であると私は信じています。たとえば–製造業では、旅行者の仕事が測定値の挿入が多いさまざまなプロセスを通過しているときに、NOLOCKヒントを使用して完了したジョブに対してクエリを安全に実行できるため、テーブルにPROMOTEDまたはEXCLUSIVEロックを配置する他のセッションとの衝突を回避できます。 /ページ。この場合にアクセスするデータは静的ですが、1分間に数億のレコードと数千の更新/挿入がある非常にトランザクションの多いテーブルに存在する場合があります。乾杯


2

nolockを使用することは事実上決して正しいことではないと私は信じています。

単一の行を読み取る場合、正しいインデックスは、個々の行のアクションが迅速に完了するため、NOLOCKが不要になることを意味します。

一時的な表示以外の多くの行を読み込んでいて、結果を繰り返したり、生成された数で防御したりできることに注意する場合、NOLOCKは適切ではありません。

NOLOCKは、「この回答に重複行、削除された行、またはロールバックのために最初に挿入されなかった行が含まれているかどうかは気にしない」の代理タグです。

NOLOCKで発生する可能性のあるエラー:

  • 一致する行はまったく返されません。
  • 単一の行が複数回返される(同じ主キーの複数のインスタンスを含む)
  • 一致しない行が返されます。

noLock選択の実行中にページ分割を引き起こす可能性のあるアクションは、これらのことを引き起こす可能性があります。ほとんどすべてのアクション(削除を含む)でページ分割が発生する可能性があります。

したがって、実行中に行が変更されないことを「知っている」場合は、nolockを使用しないでください。インデックスによって効率的に検索できるためです。

クエリの実行中に行が変更される可能性があり、正確性を重視する場合は、nolockを使用しないでください。

デッドロックが原因でNOLOCKを検討している場合は、クエリプランの構造で予期しないテーブルスキャンを調べ、デッドロックをトレースして、その原因を確認してください。書き込みの周りのNOLOCKは、以前にデッドロックしたクエリが両方とも誤った答えを書き込む可能性があることを意味します。


2

可能であれば、より良い解決策は次のとおりです。

  • データを(ログレプリケーションを使用して)レポートデータベースに複製します。
  • SANスナップショットを使用して、一貫したバージョンのDBをマウントする
  • より基本的なトランザクション分離レベルを持つデータベースを使用する

SNAPSHOTトランザクション分離レベルは、MSがOracleへの販売を失っていたために作成されました。Oracleは、この問題を回避するために、元に戻す/やり直しログを使用します。PostgresはMVCCを使用します。将来、MSのHeckatonはMVCCを使用するようになりますが、本番稼働の準備が整うまでには数年かかります。


上にタイプミスがあります。「より良い基本的なトランザクション分離メカニズム」と言っているのです。
pwy 14

1
SNAPSHOTトランザクション分離レベルは、MSの発明です。基本的には、TEMPDBの一時テーブルにデータを配置します。そのDBは、ボックス上のすべてのDB間で共有されます。したがって、可能であれば、TEMPDBにSSDを使用する必要があります。それはおそらく他のオプションよりも少ない労力です。
pwy 2014

1

NOLOCKは、データベースの読み取りを高速化する魔法の方法としてしばしば利用されますが、可能な限り使用しないようにしています。

結果セットには、まだコミットされていない、後でロールバックされることが多い行を含めることができます。

エラーまたは結果セットが空になるか、行が欠落するか、同じ行が複数回表示されることがあります。

これは、他のトランザクションがデータの読み取りと同時にデータを移動しているためです。

READ COMMITTEDは、複数のユーザーが同じセルを同時に変更する単一の列内でデータが破損するという追加の問題を追加します。


-2

すでに記述されたシステムに遭遇し、テーブルにインデックスを追加し、その後14gigデータテーブルのデータの読み込みを大幅に遅くする現実の世界では、レポートでWITH NOLOCKを使用し、月末に処理する必要があるため、集計関数(合計、カウントなど)行、ページ、テーブルのロックを行わず、全体的なパフォーマンスを決定します。新しいシステムで簡単に言うと、WITH NOLOCKを使用せず、インデックスを使用することはありません。ただし、インデックスを追加すると、データの読み込みが大幅にダウングレードされます。そして、言われたら、コードベースを変更してインデックスを削除し、一括読み込みしてからインデックスを再作成します。新しいシステムを開発している場合は、すべてが順調です。しかし、システムがすでに整っている場合はそうではありません。


1
何を言っているのですか
Max Alexander Hanna
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.