4

当社のデータベース アプリケーションでブロッキングの問題が発生している顧客がいます。Blocked Process Report トレースを実行するよう依頼したところ、SELECT 操作と UPDATE 操作の間でブロックが発生していることが示されました。トレース ファイルには、次の内容が表示されます。

  • 同じ SELECT クエリが異なる分離レベルで実行されています。1 つのトレースは Serializable IsolationLevel を示し、後のトレースは RepeatableRead IsolationLevel を示します。クエリの実行中に明示的なトランザクションは使用しません。
  • UPDATE クエリは RepeatableRead 分離レベルで実行されていますが、SELECT クエリによってブロックされています。これは、IsolationLevel が RepeatableRead の明示的なトランザクションで更新がラップされているためです。

基本的に、SELECT クエリの Isolation Level がデフォルトの ReadCommitted IsolationLevel にならない理由について途方に暮れていますが、さらに紛らわしいことに、クエリの IsolationLevel が時間の経過とともに変化するのはなぜでしょうか? この現象が見られるのは 1 人のお客様だけであるため、データベースの構成に問題がある可能性があると考えられます。

何か案は?

前もって感謝します、

グラハム

4

2 に答える 2

7

あなたのシナリオでは、分離レベルを明示的にスナップショットに設定することをお勧めします。これにより、ロックを防ぐことで読み取りが書き込み (挿入と更新) の邪魔になるのを防ぐことができますが、それらの読み取りは依然として「良い」読み取りになります (つまり、ダーティ データではありません - NOLOCK とは異なります)

通常、クエリでロックの問題がある場合、適用されるロックを手動で制御します。たとえば、ページ/テーブル レベルのロックを回避するために行レベルのロックを使用して更新を行い、読み取りを readpast に設定します (一部のシナリオでは、一部のデータが失われる可能性があることを受け入れて、問題ない可能性があります) link|edit|delete|flag

編集--すべてのコメントを回答にまとめる

最適化プロセスの一環として、SQL Server は、変更されていないことがわかっているページでコミットされた読み取りを取得することを回避し、より弱いロック戦略に自動的にフォールバックします。あなたの場合、SQLサーバーはシリアル化可能な読み取りから繰り返し可能な読み取りにドロップします。

Q: 分離レベルの削除に関する有益な情報をありがとうございます。SELECT に明示的なトランザクションを使用しないことを考えると、そもそも Serializable IsolationLevel を使用する理由を考えられますか?暗黙のトランザクションが ReadCommitted を使用することは私たちの理解でしたか?

A: デフォルトでは、SQL Server は Read Commmited がデフォルトの分離レベルである場合に使用しますが、クエリでロック戦略を追加で指定しない場合は、基本的に SQL Server に対して「最善だと思うことを行いますが、私の好みです」と言っているのと同じです。コミットされた読み取りです」。SQL Server は自由に選択できるため、クエリを最適化するために選択します。(SQL サーバーの最適化アルゴリズムは非常に複雑で、私自身も完全には理解していません)。トランザクション内で明示的に実行しなくても、SQL Server が使用する分離レベルには影響しません。

Q: 最後に、クエリを最適化するために SQL Server が分離レベル (およびおそらく必要なロックの数) を増やすことは合理的だと思いますか? 最後に使用された分離レベルを継承した場合、プールされた接続の再利用がこれに影響するかどうかも疑問に思っていますか?

A: SQL サーバーは、「ロック エスカレーション」と呼ばれるプロセスの一部としてこれを行います。http://support.microsoft.com/kb/323630から、私は引用します。通常、SQL Server の既定の動作では、ロックのエスカレーションが発生するのは、パフォーマンスが向上するポイント、または過剰なシステム ロック メモリをより適切なレベルに減らす必要がある場合のみです。ただし、一部のアプリケーションまたはクエリの設計では、望ましくないときにロックのエスカレーションがトリガーされ、エスカレートされたテーブル ロックが他のユーザーをブロックする可能性があります。

ロックのエスカレーションは、クエリが実行される分離レベルを変更することとまったく同じではありませんが、SQL Server がデフォルトの分離レベルで許可されている以上のロックを取得するとは予想していなかったので、これには驚きました。

于 2009-08-26T10:16:10.223 に答える
3

SQL がエスカレートによってより多くのロックを取得する理由に関する詳細情報: これは正しくありません。エスカレートすると、必要なロックの数が減少します (増加するのではありません)。テーブル ロックは、下位レベルから同じことを行うために必要なすべてのページ ロックまたは行ロックに対して、単一のロックです。ロックのエスカレーションが常に行われる理由は 1 つあります。すべての下位レベルのオブジェクトをロックするよりも、上位レベルのロックを取得する方が効率的です。

たとえば、効率的にロックできるインデックスがない可能性があります。つまり、フィールドに 2010 年が含まれるすべてのレコードで UPDLOCK を使用してカウントを行い、その日付フィールドにインデックスがない場合、2010 年の各レコードで行ロックが必要になります。おそらくページ間でランダムに分散されているため、ページロックも役に立たないため、SQLはテーブルロックを取得します。さらに、SQL は、UPDLOCK が保持されている間、他のレコードが 2010 年に変更されないようにロックする必要があり、このフィールドに範囲ロックを行うためのインデックスがない場合、SQL には選択肢がありませんが、これを防ぐためにテーブル ロックを取得する必要があります。 . この後者のポイントは、最適化に慣れていない人が見落としがちなポイントです。SQL も「保護」しなければならないという認識です。

于 2012-02-14T01:51:10.870 に答える