READ UNCOMMITTED分離レベルを使用する理由


225

平易な英語で、使用の欠点と利点は何ですか

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED

.NETアプリケーションとレポートサービスアプリケーションのクエリで?

回答:


210

この分離レベルでは、ダーティリードが可能です。1つのトランザクションは、他のトランザクションによって行われたコミットされていない変更を認識する場合があります。

最高レベルの分離を維持するために、DBMSは通常、データのロックを取得するため、同時実行性が失われ、ロックのオーバーヘッドが高くなる可能性があります。この分離レベルは、このプロパティを緩和します。

ウィキペディアの記事でREAD UNCOMMITTED、いくつかの例と詳細を確認することをお勧めします。


Stack Overflowの初期に彼と彼のチームがデッドロック問題にどのように取り組んだかについてのJeff Atwoodのブログ記事をチェックすることにも興味があるかもしれません。ジェフによると:

しかし、nolock危険ですか?で無効なデータを読み取ってしまう可能性がありますread uncommittedか?はい、理論的には。ACIDの科学を身につけ始めたデータベースアーキテクチャの宇宙飛行士は何も不足していないことに気づくでしょうnolock。それは本当です:理論は怖いです。しかし、私が考えるのはここにあります。「理論的には理論と実践の間に違いはありません。実際には違いがあります。」

私はnolock 、データベースのデッドロックの問題を解決するために、一般的に「問題がある場合に役立つ」スネークオイルフィックスを使用することはお勧めしません。最初に問題の原因を診断する必要があります。

しかし、実際にnolockは、絶対にわかっているクエリに追加することが単純で単純な読み取り専用の問題であっても、問題が発生することはないようです。

READ UNCOMMITTED検討する必要があるレベルの1つの代替手段はですREAD COMMITTED SNAPSHOT。ジェフをもう一度引用:

スナップショットは、まったく新しいデータ変更追跡方法に依存しています。わずかな論理的な変更ではなく、サーバーがデータを物理的に異なる方法で処理する必要があります。この新しいデータ変更追跡メソッドが有効になると、すべてのデータ変更のコピーまたはスナップショットが作成されます。競合時にライブデータではなくこれらのスナップショットを読み取ることで、読み取り時に共有ロックが不要になり、データベース全体のパフォーマンスが向上する可能性があります。


13
作者は、コミットされていない読み取り/ロックなしは最後にコミットされたデータを返すことを示唆しているようです。私の理解では、コミットされていないトランザクションは、コミットされていないトランザクションからでも最後に設定された値を返します。その場合、結果は「数秒古くなった」データを取得しません。これは(または、少なくとも、読み取ったデータを書き込んだトランザクションがロールバックされた場合)、存在しないか、コミットされていないデータを取得することになります。私は間違っていますか?
xr280xr

4
すばらしい答えです。ちなみに、Oracleはデフォルトで「スナップショット」を知っています。おそらくSQL Serverが導入する数十年前のことです。SQL Serverを使い始めたときはとてもがっかりしました。同時実行性の問題はすべて「プリミティブ」ロックメカニズムを使用して解決されていることがわかりました。Oracleで「コミットされていない読み取り」が表示されたことはありません。そして開業医は宇宙飛行士と同じくらい幸せです。
Stefan Steinegger、2011年

13
READ UNCOMMITTEDまた、行を2回読み取るか、行全体を見逃す可能性があります。読み取り中にページ分割が発生すると、データのチャンク全体が失われる可能性があります。WITH(NOLOCK)結果の精度が重要でない場合にのみ使用する必要があります
Ian Boyd

8
@DanielNolan、ジェフがをしているのわからなかったので、その記事を推奨するのは危険です。Read-uncommmitedは、データを読み取る場合にのみ意味があり、変更されることはありません。書き込まれるテーブルを読み取るためにそれを使用しようとすると、実際にはロールバックされたものを読み取ることになります。数秒前のデータを読み取っているだけでなく、.................................. ................... ‌ ‌ ........................... ....
パチェリエ

5
................................... コミットされることさえないデータを読み取っています。これが破損した読み取りのまさにその定義です。そして、それらのコミットされていない読み取りの結果基づい書き込む場合は、実際には破損したデータを書き込むことになります。また、記事では、「Webアプリで育ったMySQLは、SQL Serverよりも最初からそれほど悲観的ではない」とも述べています。trueではありません。SQLServerはデフォルトで読み取りコミットレベルで動作しますが、MySQLはデフォルトで、読み取り非コミットから5レベル離れた反復可能な読み取りで動作します。
Pacerier、2014

36

これは、長い挿入クエリの進行状況を確認しCOUNT(*)たり、大まかな見積もり(など)を行ったりする場合に役立ちますSUM(*)

つまり、ダーティリードクエリが返す結果は、それらを推定値として扱い、それらに基づいて重要な決定を行わない限り、問題ありません。


36

私のお気に入りの使用例read uncommitedは、トランザクション内で発生している何かをデバッグすることです。

デバッガーの下でソフトウェアを起動します。コード行をステップ実行している間、トランザクションが開き、データベースが変更されます。コードが停止している間、クエリアナライザーを開いて、コミットされていない読み取りの分離レベルを設定し、クエリを実行して何が起こっているかを確認できます。

また、これを使用して、長時間実行されているプロシージャがスタックしているか、またはデータベースを正しく更新しているかどうかを確認することもできます。

あなたの会社が過度に複雑なストアドプロシージャを作成することを愛するなら、それは素晴らしいことです。


6
私の会社は、過度に複雑なストアドプロシージャを作成するのが大好きです。トラブルシューティングに最適なアイデアです。
ブランドン

22

利点は、状況によってはより高速になる可能性があることです。欠点は、結果が間違っている可能性があり(まだコミットされていないデータが返される可能性があります)、結果が再現可能である保証はありません。

精度を気にする場合は、使用しないでください。

詳細はMSDNにあります:

ダーティリード、または分離レベル0のロックを実装します。つまり、共有ロックは発行されず、排他ロックは適用されません。このオプションを設定すると、コミットされていないデータやダーティデータを読み取ることができます。トランザクションが終了する前に、データの値を変更したり、データセット内の行を表示または非表示にしたりできます。このオプションは、トランザクションのすべてのSELECTステートメントのすべてのテーブルにNOLOCKを設定するのと同じ効果があります。これは、4つの分離レベルの中で最も制限が少ないものです。


これはクエリの速度にどのように影響しますか?
Kip Real

11
@Kip- selectステートメントは、他のトランザクションによって排他的にロックされているリソースの共有ロックを取得するために待機する必要はありません。
ジャロッドディクソン

15

いつ使用しても大丈夫READ UNCOMMITTEDですか?

経験則

良い:常に変化する合計を示す大きな集計レポート。

危険:ほとんどすべて。

朗報は、読み取り専用レポートの大部分がそのグッドカテゴリに分類されることです

もっと詳しく...

それを使用してOK:

  • 年初来の売上など、現在の非静的データに関するほぼすべてのユーザー向け集計レポート。エラーのマージン(おそらく0.1%未満)のリスクがあります。これは、入力エラーや、正確にデータが分ごとに記録されるときのランダム性などの他の不確実性要因よりもはるかに低いものです。

これはおそらく、ビジネスインテリジェンス部門がSSRSなどで行うことの大部分をカバーしています。もちろん例外は、その前に$記号があるものです。多くの人々は、顧客にサービスを提供し、そのお金を生成するために必要な関連するコア指標に適用されるよりもはるかに熱心にお金を占めています。(私は会計士のせいです)。

危険なとき

  • 詳細レベルに至るレポート。その詳細が必要な場合は、通常、すべての行が決定に関連していることを意味します。実際、ブロックせずに小さなサブセットをプルできない場合は、それが現在編集されているという正当な理由がある可能性があります。

  • 歴史的なデータ。実用的な違いが生じることはめったにありませんが、ユーザーは絶えず変化するデータは完璧ではないことを理解していますが、静的データについては同じとは感じていません。ダーティリードはここでは害にはなりませんが、ダブルリードが時々害を及ぼす可能性があります。とにかく静的データをブロックすべきではないのに、なぜそれを危険にさらすのでしょうか。

  • 書き込み機能も備えたアプリケーションに供給するほとんどすべてのもの。

OKシナリオでもOKでない場合。

  • 大きな単一トランザクションを利用するアプリケーションまたは更新プロセスはありますか?あなたが報告している多くのレコードを削除してから再挿入するものは?その場合NOLOCK、これらのテーブルでは何も使用できません。

レポートについての良い点。実際、最初に頭に浮かんだのはread uncommitted、データの精度がそれほど重要ではないUIグリッドをユーザーが表示するときに、Webアプリケーションに使用するべきかどうかです。ユーザーは、レコードが何であるかを簡単に確認したいだけで、ページング、並べ替え、およびフィルタリングが必要な場合があります。ユーザーが[編集]ボタンをクリックしたときのみ、より厳密な分離レベルで最新のレコードを読み取ろうとします。このようなアプローチはパフォーマンスの点で優れていると思いませんか?
JustAMartin

はい、それは合理的だと思います。より重要な問題は、編集ボタンを押してから送信するまでの間に、他の誰かによってデータが変更されていないことを確認することです。のようにデータをフェッチするトランザクションを開始することで、これを処理できselect item from things with (UPDLOCK)ます。そこにクイックタイムアウトを設定して、ロックをすばやく取得できない場合に、編集中であることをユーザーに通知します。これにより、ユーザーだけでなく開発者からも安全に保つことができます。ここで問題になるのは、タイムアウトと、UIでのタイムアウトの処理方法について考え始める必要があることだけです。
アダマン

6

レポートに関しては、すべてのレポートクエリで使用して、クエリがデータベースを停止させないようにします。マイクロ秒までのデータではなく、履歴データを取得しているので、それが可能です。


4

ソースが変更される可能性が非常に低い状況では、READ_UNCOMMITTEDを使用します。

  • 履歴データを読み取るとき。たとえば、2日前に発生したいくつかのデプロイメントログ。
  • メタデータを再度読み取る場合。たとえば、メタデータベースのアプリケーション。

フェッチ操作中にソースが変更される可能性があることがわかっている場合は、READ_UNCOMMITTEDを使用しないでください。


1
逆が当てはまると思います。まず、静的データはブロックなしで問題なく読み取る必要があります。それブロックする場合、修正すべき重要なぶら下がりトランザクションの問題があることがわかりました。また、ユーザーは、これが昨年の年次報告書に印刷したものはすべて、最後の小数点以下に一致すると予想します。彼らは一般的に彼らが知っている同じレポートが絶えず変化していることを期待していません。これは、詳細な、非常に時間に敏感な、または財務報告には当てはまりませんが、1000の1つの入力エラーが許容できる場合は許容されREAD UNCOMMITTEDます。
アダマンティッシュ2014年

TLDR:データが変更されない場合は、ブロックが存在しないため、READ UNCOMMITTEDは必要ありません。あなたが間違っていて、それが変わった場合、それはユーザーが予想よりも汚いデータを取得するのをブロックしたことは良いことです。
アダマンティッシュ

はい、私はここで@Adamantishに同意する傾向がありREAD UNCOMMITTEDます。データがアクティブに使用されており、不注意に悪用しているユーザーがいるだけでデッドロックやトランザクションのロールバックの可能性を回避するためにサーバーの負荷を軽減したい場合に、ほとんどのメリットを享受できます。データグリッドのあるWebページの[更新]ボタン。多数のレコードを同時に表示するユーザーは、通常、データが少し古いか部分的に更新されているかどうかはあまり気にしません。ユーザーがレコードを編集しようとしているときのみ、最も正確なデータを提供することができます。
JustAMartin

2

これにより、ダーティリードが得られ、まだコミットされていないトランザクションが表示されます。それが最も明白な答えです。読み取り速度を上げるためだけにこれを使用するのは良い考えではないと思います。優れたデータベース設計を使用する場合、他の方法でこれを行うことができます。

何が起こっていないかを指摘することも興味深いです。READ UNCOMMITTEDは、他のテーブルロックを無視するだけではありません。それ自体もロックを引き起こしていません。

大きなレポートを生成している場合、または大きくて複雑な可能性のあるSELECTステートメントを使用してデータベースからデータを移行している場合を考えてください。これにより、トランザクション中に共有ロックがエスカレートされる可能性があります。他のトランザクションはテーブルから読み取ることができますが、更新は不可能です。プロダクションが完全に停止する可能性があるため、プロダクションデータベースの場合、これは悪い考えかもしれません。

READ UNCOMMITTEDを使用している場合、テーブルに共有ロックを設定しません。いくつかの新しいトランザクションから結果を取得するか、データが挿入されたテーブルの場所やSELECTトランザクションが読み取った時間に依存しない場合があります。たとえばページ分割が発生した場合、同じデータが2回取得される場合もあります(データはデータファイル内の別の場所にコピーされます)。

したがって、SELECTの実行中にデータを挿入できることが非常に重要な場合は、READ UNCOMMITTEDが意味をなす場合があります。レポートにはいくつかのエラーが含まれる可能性があることを考慮する必要がありますが、数百万の行に基づいており、結果の選択中に更新されるのがほんの数行である場合、これで十分です。行の一意性が保証されない場合があるため、トランザクションがすべて失敗することもあります。

全体としては、SNAPSHOT ISOLATION LEVELを使用することをお勧めしますが、これを使用するには、アプリケーションでいくつかの調整が必要になる場合があります。この1つの例は、アプリケーションが行を排他的にロックして、他のユーザーが行を読み取らないようにし、UIで編集モードに入る場合です。SNAPSHOT ISOLATION LEVELには、パフォーマンスがかなり低下します(特にディスク上)。しかし、問題にハードウェアを投入することでそれを克服することができます。:)

データウェアハウスへのデータのレポートまたはロードに使用するデータベースのバックアップを復元することも検討できます。


0

これは、既存の行への更新がなく、他のテーブルへのfkがない、挿入のみの監査テーブルなどの単純なテーブルに使用できます。挿入は単純な挿入であり、ロールバックの可能性はほとんどありません。


-7

今は常にREAD UNCOMMITTEDを使用しています。問題が少なく、高速です。他の分離を使用すると、ほとんどの場合、いくつかのブロッキングの問題に遭遇します。

自動インクリメントフィールドを使用し、挿入にもう少し注意を払う限り、罰金を科せば、問題をブロックするのに別れを告げることができます。

READ UNCOMMITEDを使用するとエラーが発生する可能性がありますが、正直に言うと、挿入が完全であることを確認するのは非常に簡単です。選択からの結果を使用する挿入/更新は、注意する必要がある唯一のものです。(ここでREAD COMMITTEDを使用するか、ダーティーリードが問題を引き起こさないことを確認してください)

Dirty Reads(特に大きなレポートの場合)を実行すると、ソフトウェアがよりスムーズに実行されます...


6
これは非常に不正確であり、nolockで発生する可能性のある問題の表面にのみ触れます。ページが分割されたり、結合が失敗したり、存在しないデータを読み取ったり、データを複製したりできます。その使用を完全なものにする方法はありません。この分離レベルでは、何の精度も信頼できません。
コミットされたスナップショットの読み取り

@MarkSowulこの回答の反対投票は私には不公平に思えます。@Cliveは、彼Committedが挿入と更新に切り替えることを明確にしました。他の問題については、自動インクリメントキーの使用について言及する際に、ページ分割の問題を認識していることも示しました。人間だけで読まれるように作成されたほぼすべてのライブレポートは、最終的な小数点以下のわずかな差異を許容できると彼は同意します。機械で読み取って変換する予定の詳細なリストやデータについては別の話であり、Cliveもそうだと思います。
アダマンティッシュ2014年

1
このコメントは、nolockで発生する可能性のある問題を完全に理解していないことも示しています。「小数点以下のわずかな差異」ではほとんどカバーできません。「挿入/更新のためにコミットされた読み取りのみを使用する」に触れても、一般的なアドバイスとして間違っています(「レコードが存在しない場合にレコードを挿入する」の場合はどうでしょうか?)。いずれにせよ、「[コミットされていない読み取り]は、問題が最も少なく、高速です」は間違いなく間違っています。
Mark Sowul 2014年

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