15 個のテーブルのデータを保存/更新する必要があります。ダーティ リードが発生しないように、更新時に同時実行性とロックを維持する必要があります。ストアド プロシージャを使用してデータを更新しています。ロックと同時実行を実装するために oredr で何ができますか?
4 に答える
他の回答は、すでにトランザクションを使用していることを前提としています。見逃しているかもしれないので省略しません。
トランザクションを使用して、15 個のテーブルすべてのレコードが挿入/更新されるか、まったくレコードが挿入/更新されないようにする必要があります。トランザクションは、操作の原子性を保証します。ストアド プロシージャ中に何かが失敗し、トランザクションを使用しない場合、いくつかの保存/更新操作が行われ、いくつかは行われません (エラーを生成したクエリからのもの)。
BEGIN TRANと COMMIT を使用して操作を成功させるか、失敗した場合に ROLLBACK を使用すると、すべてが完了するか、何も行われません。各クエリの実行後にエラーをチェックし、エラーがある場合は ROLLBACK TRANSACTION を呼び出すか、ストアド プロシージャの最後で COMMIT を呼び出す必要があります。
ストアド プロシージャ内でトランザクションを処理する方法に関するこの Stackoverflow の質問の受け入れられた回答には、良いサンプルがあります。
トランザクションを取得したら、2 番目の部分は、ダーティ リードを回避する方法です。データベースの分離レベルを READ COMMITED に設定できます。これにより、デフォルトでデータのダーティ リードが防止されます。ただし、クエリでWITH (NOLOCK) または READUNCOMMITEDを指定することにより、ダーティ リードを実行することもできます。それを防ぐことはできません。
さらに、ロックを防ぐことができるスナップショット分離レベル (スナップショットとコミットされたスナップショットの読み取り) があり (これは常に良いとは限りません)、ダーティ リードを同時に回避します。
このトピックに関する多くの文献がインターネット上にあります。スナップショット分離レベルに興味がある場合は、Brent Ozar の Kendra Little によるこの素晴らしい記事を読むことをお勧めします。
ダーティ リードが発生しないことを防ぐことはできません。ダーティ リードを行うのはリーダーであり、あなた (ライター) ではありません。できることは、書き込みがアトミックであることを確認することだけです。これは、すべての書き込みを単一のトランザクションにラップすることによって実現されます。このようにして、ダーティ リードを発行しないリーダーは、すべての更新を表示するか、まったく表示しない (アトミック) かのいずれかになります。
リーダーがダーティ リードを発行することを選択した場合、それに対してできることは何もありません。
分離レベルを変更しても、リーダーの分離レベルにはまったく影響しないことに注意してください。
SQL Server の分離レベルが適切に設定されていることを確認するために必要なことはすべてです。ダーティ リードを排除するには、 Read Committed以上である必要があります( Read Uncommittedではありません)。Read Committedは、すぐに使用できるデフォルト設定です。
ただし、上記のリンクを確認して、より高い設定が提供する利点 (および結果) を確認することは価値があるかもしれません.
トランザクション分離レベルを SERIALIZABLE に設定できます。次のステートメントを使用して
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION の前に警告しますが、テーブルにデータを更新または挿入しようとする他のユーザーの速度が低下する可能性があります。最後にコミット/保存されたデータのみを表示する SNAP_SHOT 分離レベルを利用することもできますが、パフォーマンスに影響を与える可能性のある一時データベースの広範な使用。