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