ご存じのとおり、READ UNCOMMITTEDは、ダーティリードやファントムリードなどが発生する可能性がある最低の分離レベルです。この分離レベルを使用するのに最適な時期はいつですか、どのような理由で使用されるのですか?
実は前に答えを読んでみましたが、例が少ないので完全には理解できませんでした。
ご存じのとおり、READ UNCOMMITTEDは、ダーティリードやファントムリードなどが発生する可能性がある最低の分離レベルです。この分離レベルを使用するのに最適な時期はいつですか、どのような理由で使用されるのですか?
実は前に答えを読んでみましたが、例が少ないので完全には理解できませんでした。
回答:
SSMSから運用データベースにクエリを実行するときにREAD_UNCOMMITTED
(またはNOLOCK
)を使用していますが、アプリケーションコードからは定期的に実行していません。この方法(およびMAXDOP 1クエリヒント)は、結果が正しくない可能性があることを理解した上で、データ分析およびトラブルシューティングのためのカジュアルなクエリが本番ワークロードに影響を与えないようにするのに役立ちます。
悲しいことに、私が見るREAD_UNCOMMITTED
/ NOLOCK
データの整合性を犠牲にしてブロックを回避するために、生産コードで広く使われています。適切な解決策は、行バージョンの分離レベルである(SNAPSHOT
またはREAD_COMMITTED
でREAD_COMMITTED_SNAPSHOT
データベース・オプションON
)及び/又はクエリとインデックスチューニングに注目。
最近、コードをレビューしましたが、NOLOCK
間違った結果が返されることがあるので、変更が唯一の変更でした。削除NOLOCK
は良いことでしたが、行の欠落または重複は通常、大きなテーブルの割り当て順序のスキャン中に発生することを知っていたので、UNION ALL
インデックスの効率的な使用を促進する手法をリファクタリングすることも提案しました。クエリは数ミリ秒で実行され、すべての世界で最高の正しい結果が得られます。
私は、それの罰金を考えて、いくつかのあなたは結果を受け入れ、他のオプションを持っていない限り、状況。
他のオプションについては、新しいアプリケーションにはRead Committed Snapshot Isolation(RCSI)を、古いアプリケーションにはSNAPSHOT ISOLATION(SI)を使用するように人々を促します。RCSIで競合状態のコードベース全体を簡単にテストすることはできません。
ただし、それらは適切ではない場合があります。tempdbの愛情と思いやりに余分な時間を費やし、バージョンストア(およびtempdb)を拡張してディスクをいっぱいにするトランザクションを開いたままにしないようにする必要がある場合があります。
DBAやSQL Serverの監視と管理を担当する人がいない場合、これらのオプションは危険な場合があります。より一般的には、誰もがサーバーに送信されるコードを完全に制御できるわけではなく、接続文字列またはコードを変更して、問題のクエリのSIを要求できます。
さらに、ほとんどの人はアプリケーション全体でロックの問題を抱えていません。彼らはOLTPデータのレポートなどの問題を抱えています。ライターによってブロックされていないレポートと引き換えに、NOLOCK / RUのトレードオフを受け入れることができる場合は、それに従ってください。
それが何を意味するかを理解していることを確認してください。これは、クエリがロックを取得しないことを意味するのではなく、他のクエリによって取得されたロックを尊重しないことを意味します。
そしてもちろん、問題がライター/ライターのロックである場合、役立つ唯一のオプションはSIですが、エラー処理などで適切に実装するには、開発者の多大な労力が必要になります。
ヘルスケアでいつも使っています。
データの個々の行がクエリの途中で変更されることは驚くほどまれであり、読み取り/書き込みの比率は10,000 / 1です。これらのほとんどは挿入であり、更新ではありません。たとえば、ラボインターフェイスが患者のラボ結果をデータベースに書き込む場合、これらの値は決して変更されません。
データが変更されると、一度に1行ずつ変更されます。誰もが列全体を更新していません(DBAが実際に失敗した場合を除く)。
一方、一連のクエリを実行して、患者が72時間以内にERに戻ってくるようなものをスキャンします。これにより、テーブルが完全に破壊されます。
SQLの10年間で、私はを見たことがありませんRollback Transaction
。エンドユーザーエクスペリエンスを中断せずに出入りしたい。OLTPデータベースの速度が低下するリスクが高く、不良データを取得するリスクが低い場合は、NOLOCKを実行します。
それを使うべきでしょうか?多分そうでないかもしれません。一般的に言って、これまで取り組んできたアプリケーションデータベースの多くが適切に設計されているとは言えません。彼らは通常アンチパターンで一杯です。
READ_UNCOMMITTED/NOLOCK
データの正確さが本当に主な目的ではない場合、これは良いオプションです。概算の集計数で十分な場合もあります。例:テーブルのINSERTまたはUPDATEに使用されるストアドプロシージャがあります。更新または挿入されるレコードの数が膨大になる場合があります(数千のレコード)。これらのストアドプロシージャの実行中NOLOCK
、ターゲットテーブルで定期的にシンプルな選択クエリを実行して、スムーズに進行するかどうかを確認できます(更新クエリの場合、更新されるレコードのステータス変更列がある場合、その列を使用してgroup by
クエリを実行できますNOLOCK
ステータス変更カウントが常に変化しているかどうかを確認します)。
READ UNCOMMITTEDを使用すると、ダーティリードだけでなく、一貫性に関する追加の問題が生じることに注意してください。アクセス方法によっては、行を見逃したり、同じ行を複数回読み取ったりする場合があります。詳細に興味がある場合は、Itzik Ben-Ganの記事を読んでください。