web-dev-qa-db-ja.com

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

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

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

また、デッドロックが発生している場合、それは素晴らしい解決策であると言われました。そのため、SQLの第一人者がランダムコードを手伝ってくれて、SQLコードのすべてのNOLOCKSに気づくまで、数年間その考えを追い始めました。私は丁寧にoldられ、彼はそれを私に説明しようとしました(なぜそれが良いことではないのか)そして私はちょっと迷子になりました。彼の説明の本質は、「それがより深刻な問題に対するバンドエイドの解決策だと感じた..あなたがデッドロックを経験している場合は特にそうだ」。そのため、問題の根本を修正してください。

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

だから、いくつかのSQL DBの第一人者の先生が私を啓発してくれますか?

121
Pure.Krome

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

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

スナップショット分離が役立つとき、および痛いとき を読むことをお勧めします。MSDNは、ほとんどの状況でSNAPSHOTではなくREAD COMMITTED SNAPSHOTを使用することをお勧めします。

66
OMG Ponies

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

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

そして、教祖の説明は正しかった。これは通常、より深刻な問題に対するバンドエイドソリューションです。

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

20
Mitch Wheat

交通量の多い経験があるのは「教祖」だったに違いない...

通常、Webサイトは、ユーザーが完全に読み込まれたページを表示するまでに「ダーティ」になります。データベースからロードし、編集されたデータを保存するフォームを検討してください??ダーティリードについての人々のやり方は、そんなにダメです。

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

一方、Webサイトの高度な製品検索(つまり、キャッシュされず、集中的になる可能性のあるもの)があり、同時に複数のユーザー(現象的な数「専門家」はそうではありません)、その背後にある他のすべてのプロセスをボトルネックにすることはやりがいがあります。

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

EDIT:デッドロックだけでなく、終了するまで他の人をどれだけ待たせるか、またはその逆です。

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

13
Gats

間違った答えはありませんが、少し混乱するかもしれません。

  • 単一の値/行をクエリする場合、always NOLOCKを使用するのは悪い習慣です。間違った情報を表示したり、間違ったデータに対して何らかのアクションを実行したりすることはおそらくないでしょう。
  • 大まかな統計情報を表示する場合、NOLOCKは非常に便利です。例としてSOを使用します。ロックを取得してexact質問の表示回数、またはタグの正確な質問数を読み取るのは無意味です。 「sql-server」でタグ付けされた3360の質問を誤って述べた場合、誰も気にしません。また、トランザクションのロールバックのため、1秒後に3359の質問があります。
9

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

読む ヒントと他の貧しいアイデア

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

ルーク

2
luckyluke

可能であれば、より良いソリューションは次のとおりです。

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

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

2
pwy

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

2
richard101

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

2
user2041151

Nolockを使用することは事実上決して正しいとは思わない。

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

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

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

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

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

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

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

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

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

2
Andrew Hill

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

結果セットには、まだコミットされていない行が含まれる場合がありますが、多くの場合、後でロールバックされます。

エラーまたは結果セットは空であるか、行が欠落しているか、同じ行が複数回表示される場合があります。

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

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

1