SQL Serverの「with(nolock)」とは何ですか?


610

誰かwith (nolock)がクエリで使用することの意味を説明することはできますか?

たとえば、トランザクション率が高く、特定のテーブルに大量のデータが含まれるバンキングアプリケーションがある場合、どのタイプのクエリでノーロックでも問題ありませんか?常に使用すべき/使用しないというケースはありますか?



1
ここで一つのリンク- mssqltips.com/sqlservertip/2470/...
スチーム

回答:


461

WITH(NOLOCK)は、トランザクション分離レベルとしてREAD UNCOMMITEDを使用するのと同じです。そのため、後でロールバックされるコミットされていない行、つまりデータベースに入れられなかったデータを読み取るリスクがあります。したがって、他の操作による読み取りのデッドロックを防ぐことができますが、リスクが伴います。トランザクション率の高い銀行アプリケーションでは、それをIMHOで解決しようとしている問題の適切な解決策にはならないでしょう。


156
ほとんどの銀行業務アプリケーションは、ビジネスの意味でトランザクション対応であるため、nolockを安全に使用できます。新しい行を書き込むだけで、更新することはありません。
ジョナサンアレン

49
@ Grauenwolf-挿入されたがコミットされていない行がダーティリードを引き起こす可能性があります。
サースマン2009年

16
@ Saasman-トランザクションをロールバックしない場合、それは問題ではありません。また、挿入のみのテーブルでは、ロールバックの可能性はほとんどありません。それらが発生した場合でも、1日の終わりの分散レポートですべて修正します。
ジョナサンアレン

1
私は定着しています。追加されたロックなしのヒントがオンになっていると思います。試験の場合:
ロスブッシュ

11
NOLOCKと一緒に使用するとSELECT、選択中にデータがテーブルに挿入(または更新)された場合に同じ行(重複データ)を複数回返すリスクがあります。
Ian Boyd

170

問題はもっと悪いことです:

  • デッドロック、または
  • 間違った値?

財務データベースの場合、デッドロックは間違った値よりもはるかに悪いです。私はそれが逆に聞こえることを知っていますが、私に聞いてください。DBトランザクションの従来の例では、2つの行を更新し、1つの行から減算して別の行に追加します。それは間違いです。

財務データベースでは、ビジネストランザクションを使用します。つまり、各アカウントに1行追加します。これらのトランザクションが完了し、行が正常に書き込まれることが最も重要です。

アカウントの残高を一時的に間違って取得することは大したことではありません。それが、1日の調整の目的です。また、2つのATMが同時に使用されているため、データベースからのコミットされていない読み取りよりも、アカウントからの当座借越が発生する可能性がはるかに高くなります。

そうは言っても、SQL Server 2005はNOLOCK必要になったほとんどのバグを修正しました。したがって、SQL Server 2000以前を使用している場合を除き、必要ありません。

さらに詳しい
行レベルのバージョン管理


22
一時的に間違った口座残高を得ることは大したことではありませんか?その取引が、当座貸越の限度なしにATMから現金を引き出す取引である場合はどうなりますか?
学習

13
@学習:誰かがあなたのカードを請求する30秒前にお金を引き出すとどうなりますか?すべての通信が非常に瞬時に行われるまで、当座貸越は現実の事実となります。
ジョナサンアレン

6
+1金融アプリ(どこでも、銀行だけでなく)では、更新も削除もありません。誤った操作であっても、レコードを挿入することで修正されます。この用語は英語で何ですか?「storno」ですか?グーグルは私がこの質問に答えるのを助けませんでした
Gennady VaninГеннадийВанин

7
後期エントリ...デッドロックをキャッチして再試行する必要があります。ダーティリードは結果をもたらす
gbn 2011

4
@JonathanAllenは単なるfyiであり、用語はUPではなくUTmostです。
ジミーD

57

残念ながら、それはコミットされていないデータを読み取ることだけではありません。バックグラウンドでは、ページを2回読む(ページ分割の場合)か、ページを完全に見逃す可能性があります。そのため、結果が著しく歪んでいる可能性があります。

チェックアウトItzikベン・ガンの記事を。ここに抜粋があります:

"NOLOCKヒントを使用して(またはセッションの分離レベルをREAD UNCOMMITTEDに設定して)、SQL Serverに一貫性を期待しないことを通知します。そのため、保証はありません。ただし、"一貫性のないデータ "は、後でロールバックされたコミットされていない変更、またはトランザクションの中間状態でのデータ変更が表示される場合があります。また、すべてのテーブル/インデックスデータをスキャンする単純なクエリで、SQL Serverがスキャン位置を失うか、結果的に同じ行を2回取得します。」


5
さらに少し下に彼は同じ行を2回取得する方法を説明します。col1のクラスター化インデックスがオプションIGNORE_DUP_KEYで一意のインデックスとして定義されるように、テーブルT1を再作成します。これは、col1に重複する値が存在できないこと、および重複するキーを挿入しようとしてもトランザクションが失敗せず、警告が生成されるだけでなくエラーが生成されることを意味します。 この奇妙なオプションを使用しない場合、行を2回取得することについて心配する必要はおそらくありません
JanHudecek

ワイヤードオプションがなくても、重複行を取得できます。たとえば、クエリが一意でないインデックスを利用している場合などです。ただし、これはnolockに固有のものではありません。
RMD 2013年

54

nolockヒントの正当な使用法のテキストブックの例は、高更新OLTPデータベースに対するレポートサンプリングです。

話題の例を取る。大規模な米国のハイストリートバンクが銀行で都市レベルの実行の最初の兆候を探す1時間ごとのレポートを実行したい場合、nolockクエリは、都市ごとの預金と現金引き出しを合計するトランザクションテーブルをスキャンできます。このようなレポートの場合、ロールバックされた更新トランザクションによって発生するエラーのごく一部は、レポートの価値を低下させません。


31

金融取引をデータベーストランザクションでラップしない理由がわからない(ある口座から別の口座に資金を移動するとき-一度に取引の片側をコミットしない-これが明示的な取引が存在する理由です)。コードがビジネストランザクションのように頭の痛い場合でも、すべてのトランザクションデータベースは、エラーや障害が発生したときに暗黙のロールバックを実行する可能性があります。この議論はあなたの頭上にある方法だと思います。

ロックの問題がある場合は、バージョニングを実装し、コードをクリーンアップします。

ロックなしでは、誤った値が返されるだけでなく、幻のレコードと重複が返されます。

クエリの実行が常に速くなるというのはよくある誤解です。テーブルに書き込みロックがない場合、違いはありません。テーブルにロックがある場合、クエリは速くなりますが、そもそもロックが発明された理由があります。

公平を期して、nolockヒントが実用性を提供する2つの特別なシナリオを次に示します。

1)ライブOLTPデータベースに対して長いクエリを実行する必要がある2005年より前のSQLサーバーデータベース

2)レコードをロックし、制御をUIに戻す不適切に記述されたアプリケーションとリーダーは、無期限にブロックされます。アプリケーションを修正できない場合(サードパーティなど)、データベースが2005年より前であるか、バージョン管理をオンにできない場合は、ここでNolockが役立ちます。


11
私は、NOLOCKが不十分に書かれたコードを補うために使用されるべきではないことに同意します。ただし、ジョナサンがデータベーストランザクションについて実際に言及したことはないので、ジョナサンへの攻撃は不当だと思います。彼は、金融アプリケーションは通常、レコードの編集を許可しないことを指摘していました(明らかにいくつかの例外があります)。あなたの口座振替の例では、彼はあなたがした場合、それは奇妙だろう言って変異させるのではなく、口座の残高の価値を付加する種類の台帳へのデビット/クレジットエントリを。
chrnola 14

19
別の銀行のある口座から別の口座に資金が送金されると、どうなると思いますか?一部のUberデータベースは、バンクオブアメリカのテーブルとウェルズファーゴのテーブルをロックしていますか?いいえ。金融取引はそれぞれに書き込まれ、その後、1日の終わりのプロセスですべてのレコードが一致することを確認します。
ジョナサンアレン

24

NOLOCKはと同等ですがREAD UNCOMMITTED、MicrosoftはUPDATEor DELETEステートメントに使用しないでくださいと言っています:

UPDATEまたはDELETEステートメントの場合:この機能は、Microsoft SQL Serverの将来のバージョンで削除される予定です。新しい開発作業ではこの機能を使用せず、現在この機能を使用しているアプリケーションの変更を計画してください。

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

この記事はSQL Server 2005に適用されるため、NOLOCKそのバージョンを使用している場合はのサポートが存在します。(ダーティリードの使用を決定したと仮定して)コードを将来にわたって使用するために、これをストアドプロシージャで使用できます。

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED


21

データを読み取るだけの場合に使用でき、まだコミットされていないデータを取得するかどうかは特に気にしません。

読み取り操作の方が高速になる可能性がありますが、実際にはどの程度かはわかりません。

一般に、私はそれを使用しないことをお勧めします-コミットされていないデータを読み取ることは、せいぜい少し混乱する可能性があります。


1
SQL Server 2005には行のバージョン管理があるため、nolocksが不要になるという事実に言及した方がいいでしょう。
ジョナサンアレン

まあ、 "with(nolock)"はSQL Server 2005でも引き続き使用できますが、利点はますますスリムになっています。それは事実です。
marc_s 2009年

18

通常は問題ないもう1つのケースは、データがおそらく古く、書き込みが行われないレポートデータベースです。ただし、この場合、デフォルトの分離レベルを変更して、管理者がデータベースまたはテーブルレベルでオプションを設定する必要があります。

一般的なケースでは:あなたがしているとき、あなたはそれを使用することができ非常に確認してください、それは古いデータを読み取るために大丈夫だということ。覚えておかなければならない重要なことは、それを誤解するのは非常に簡単なことです。たとえば、クエリを作成する時点で問題がなくても、これらの更新をより重要にするために、将来データベースで何かが変更されることはないと確信していますか?

また、銀行のアプリでそれはおそらく良い考えではないという考えも2つ目にします。または在庫アプリ。またはトランザクションについて考えているところはどこでも。


4
銀行のアプリケーションを扱う人として、私はノーロックが問題ではないと言わざるを得ません。トランザクションレコード、つまり挿入されたが更新または削除されなかった行は、コミットされていないデータの読み取りの問題に対して驚くほど耐性があります。
ジョナサンアレン

15

簡単な答え-SQLがデータを変更しておらず、(ロックを介して)他のアクティビティに干渉する可能性があるクエリがある場合。

特にクエリが1秒以上かかる場合は、レポートに使用されるクエリを検討する価値があります。

これは、OLTPデータベースに対して実行しているOLAPタイプのレポートがある場合に特に便利です。

しかし、最初に尋ねる質問は、「なぜこれを心配しているのですか?」です。私の経験では、デフォルトのロック動作の曖昧さは、誰かが「何かを試す」モードにあるときにしばしば発生します。これは、予期しない結果が発生する可能性が低いケースの1つです。多くの場合、これは時期尚早の最適化のケースであり、「念のため」にアプリケーションに埋め込まれたままにしておくのは簡単すぎる可能性があります。なぜそれを行っているのか、どのような問題が解決されているのか、そして実際に問題があるのか​​どうかを理解することが重要です。


11

簡潔な答え:

WITH (NOLOCK)クラスタ化インデックスを持つテーブルのSELECTステートメントでのみ使用します。

長い答え:

WITH(NOLOCK)は、データベースの読み取りを高速化する魔法の方法としてよく利用されます。

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

WITH(NOLOCK)が非クラスター化インデックスを持つテーブルに適用される場合、行データが結果テーブルにストリーミングされるときに、他のトランザクションによって行インデックスを変更できます。これは、結果セットで行が欠落したり、同じ行が複数回表示されたりする可能性があることを意味します。

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


2
最終決定を変更しない場合は、コミットされていないデータの読み取りは許容されます。たとえば、小売店が今後6か月でいくら稼げるかを予測する場合、タミーが実際に3枚を購入したときに2巻のペーパータオルを購入したことを確認しても、将来の見方は変わりません。 。
ジョナサンアレン

1
フィルターに今含まれている場合、クエリを実行した瞬間にデータが不正確になります。フィルターに履歴データのみが含まれている場合、使用してREAD UNCOMITTED も影響はありません。ANSI規格に含まれているのには理由があります。
ジョナサンアレン

2
絶対とは絶対言うな。データを100%正確にする必要がある場合は、nolockを使用しないでください。私にとって、これは通常そうではありません。ユーザーにデータを提示するとき、ユーザーがデータを操作するときまでに、データはすでに変更されている可能性がありますが、変更されていない可能性が高く、ロックの競合は応答遅延の価値がありません。
投稿者

存在価値のあるシステムに固執しましょう。Tammyの頭脳は完全にまともであることを忘れないでください。データベースを使用して、誰も気づかない小さなペーパータオルの購入を記録するのは、せいぜい途方もないことです。私たちが重点を置いているのは、実際に重要なシステムです。たとえば、時間どおりに人にお金を支払ったり、緊急事態に対応したりします。WITH(NOLOCK)の使用が、存在に値するシステムをプログラミングしている人に理解されることは大きな利点です。人がデータベースよりも良い仕事をすることができるとき、それらのリソースを転用することを検討してください。
WonderWorker

10

私の2セント- WITH (NOLOCKレポートを生成する必要があるときに使用するのは理にかなっています。この時点では、データはあまり変化せず、それらのレコードをロックする必要はありません。


2
現在の変更を気にしないのであれば、WITH(NoLOCK)の方が良いと思います。
Abdul Saboor 2013年

9

あなたが金融取引を扱っているなら、あなたは決して使いたくないでしょうnolocknolock更新が多い大きなテーブルから選択するのに最適であり、取得したレコードが古くなっている可能性があるかどうかは気にしません。

財務レコード(およびほとんどのアプリケーションの他のほとんどすべてのレコード)nolockは、書き込み中のレコードからデータを読み取る可能性があり、正しいデータを取得できない可能性があるため、大混乱を引き起こします。


5
驚いたことに、財務データを扱う場合、これは問題ではありません。行が編集されることはなく、1日の終わりにアカウントが調整されるため、一時的に偽のデータを読み取っても何も起こりません。
ジョナサンアレン

8

私は、やることのために「次のバッチ」を取得するために使用しました。この場合、どのアイテムが正確であるかは関係ありません。多くのユーザーが同じクエリを実行しています。


1
実行する作業のキューをバックグラウンドタスクに提示するのと同じようなことをします。特定のレコードに到達したときに、それが存在しないか、選択基準に一致しない場合は、次のレコードに移動します。
TripeHound 2014

7

「ダーティ」データで問題がなければ、nolockを使用します。つまり、nolockは、変更中のデータやコミットされていないデータを読み取ることもできます。

通常、トランザクションの多い環境で使用することはお勧めできません。そのため、クエリのデフォルトオプションではありません。


3
必要なのは、トランザクションの多い環境だけです。テーブルがほとんどアイドル状態の場合、それによって何も得られません。
ジョナサンアレン

7

特に(nolock)ヒントを使用して、アクティビティの多いSQLServer 2000データベースで使用します。ただし、SQL Server 2005で必要になるかどうかはわかりません。私は最近、クライアントのDBAの要求に応じてSQL Server 2000にそのヒントを追加しました。彼が多くのSPIDレコードロックに気付いていたからです。

私が言えることは、ヒントを使用しても害はなく、ロックの問題が解決したようだということです。その特定のクライアントのDBAは、基本的にはヒントを使用するように要求しました。

ちなみに、私が扱っているデータベースはエンタープライズメディカルクレームシステムのバックエンドなので、多くの結合で数百万のレコードと20以上のテーブルについて話しています。通常、結合の各テーブルにWITH(nolock)ヒントを追加します(派生テーブルでない限り、その特定のヒントは使用できません)。


1
SQL Server 2005は、nolockの必要性を大幅に減らす「行のバージョン管理」を追加しました。最近アップグレードしましたが、DBAの使用を停止するようにトレーニングしていません。
ジョナサンアレン

5

最も単純な答えは単純な質問です-再現性のある結果が必要ですか?はいの場合、NOLOCKSはどのような状況でも適切ではありません。

再現性が必要ない場合、特にターゲットデータベースに接続するすべてのプロセスを制御できない場合は、nolocksが役立つことがあります。

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