129

私はミッションクリティカルではないウェブサイトやアプリケーションを作成するビジネスをしています->例:銀行のソフトウェア、宇宙飛行、集中治療監視アプリケーションなど。あなたはアイデアを得ることができます。

それで、その大規模な免責事項で、いくつかのSQLステートメントでNOLOCKヒントを使用するのは悪いですか?数年前、SQL管理者の仲間から、「ダーティリード」に満足している場合は、NOLOCKを使用するように提案されました。これにより、各リードがロックされないため、システムのパフォーマンスが少し向上します。テーブル/行/何でも。

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

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

だから、いくつかのSQLデータベースの第一人者の先生は私を教えてくれますか?

4

12 に答える 12

109

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

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

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

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

答えが「いいえ」の場合は、を使用NOLOCKしてパフォーマンスを向上させます。


Stack Overflowのコードベース内でキーワードをすばやく検索したNOLOCKところ、138個のインスタンスが見つかったため、かなりの数の場所で使用しています。

于 2009-09-21T06:25:28.367 に答える
70

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

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

スナップショットアイソレーションが役立つ場合と問題がある場合を読むことをお勧めします。MSDNでは、ほとんどの場合、SNAPSHOTではなくREADCOMMITTEDSNAPSHOTを使用することをお勧めします。

于 2009-09-21T05:25:04.200 に答える
20

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

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

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

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

于 2009-09-21T05:24:42.280 に答える
13

交通量の多い経験をしたのは間違いなく「達人」だった...

Webサイトは通常、完全にロードされたページを表示するまでに「ダーティ」になります。データベースからロードして、編集したデータを保存するフォームを考えてみてください。汚い読み取りがそんなにノーノーであるということについて人々が続けるのはばかげています。

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

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

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

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

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

于 2011-02-23T14:54:44.317 に答える
10

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

  • 単一の値/行をクエリする場合、NOLOCKを使用することは常に悪い習慣です。おそらく、誤った情報を表示したり、誤ったデータに対して何らかのアクションを実行したりすることはありません。
  • 大まかな統計情報を表示する場合、NOLOCKは非常に便利です。例としてSOを取り上げます。質問のビューの正確な数、またはタグの質問の正確数を読み取るためにロックを取得することは意味がありません。現在「sql-server」でタグ付けされた3360の質問を誤って記述しても、誰も気にしません。トランザクションのロールバックのため、1秒後に3359の質問があります。
于 2010-08-18T12:28:06.967 に答える
2

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

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

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

ルーク

于 2011-02-23T16:46:21.880 に答える
2

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

于 2012-12-21T14:41:10.733 に答える
2

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

于 2013-02-04T21:56:25.617 に答える
2

可能な場合、より良い解決策は次のとおりです。

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

SNAPSHOTトランザクション分離レベルは、MSがOracleへの販売を失っていたために作成されました。Oracleは、この問題を回避するためにundo/redoログを使用します。PostgresはMVCCを使用します。将来、MSのHeckatonはMVCCを使用する予定ですが、それは本番環境に対応するまでには何年もかかります。

于 2014-02-07T22:36:14.643 に答える
2

nolockを使用することは事実上決して正しくないと思います。

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

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

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

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

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

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

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

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

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

于 2014-10-02T22:23:38.503 に答える
1

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

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

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

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

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

于 2016-02-05T15:48:45.697 に答える
-2

すでに作成されたシステムに遭遇し、テーブルにインデックスを追加すると、14ギガデータテーブルのデータ読み込みが大幅に遅くなる実際の生活では、レポートでWITH NOLOCKを使用し、月末に処理を行うことを余儀なくされることがあります。 、カウントなど)行、ページ、テーブルのロックを行わず、全体的なパフォーマンスを低下させます。新しいシステムでは、WITH NOLOCKを使用せず、インデックスを使用することは簡単ではありませんが、インデックスを追加すると、データの読み込みが大幅にダウングレードされます。その後、コードベースを変更してインデックスを削除し、一括読み込みしてからインデックスを再作成するように指示されたら、新しいシステムを開発している場合は、すべてうまくいきます。ただし、システムがすでに導入されている場合はそうではありません。

于 2016-08-10T09:41:10.367 に答える