待機時間が長いネットワークを介してSQL Serverデータベースを1回呼び出している場合、その待機時間が原因でテーブルロックが発生しますか?いくつかのレコードについてテーブルAにクエリを実行し、SQL Serverは低速のネットワークを介してそのデータを返す必要があるとします。サーバーがネットワーク経由で応答を送信している間、テーブルAに読み取りロックがあるか、SQL Serverが送信前にロックを解放しますか応答?
また、回答のサイズによって回答は異なりますか?数KBから数百MBを返す必要があるだけの場合、それは違いますか?
明示的なトランザクションを作成し、クエリを実行し、トランザクションを閉じると、トランザクションの継続時間が私の待ち時間と相関関係があるため、テーブルがロックされることは明らかです。
クライアントがデータの受信に長い時間がかかり、SQL Serverが待機する必要があるデータを受信したことを示す確認応答をSQL Serverに送信する場合、この待機のため、SQL Serverはクライアントから確認応答を受信しない限り、クエリが保持しているロックを解放しません。
これは正確ではなく、分離レベルに依存します。
デフォルトではREAD COMMITTED
ロックは、ステートメントの実行中は保持されません。 READ COMMITTED
はステートメントレベルの読み取りの一貫性を提供しません。唯一の保証は、コミットされていないデータを読み取れないことです。行を読み取るために共有ロックが取得および保持され、その後解放されます。
LOBタイプがない限り。
LOBタイプは非常に大きくなる可能性があるため、バッファリングできません。共有ロックは、ステートメントが完了するまで取得および保持する必要があり、基本的にREPEATABLE READ
での動作READ COMMITTED
。
高遅延ネットワークを介してMSSQLデータベースを1回呼び出している場合、その遅延のためにテーブルロックが発生しますか?
レイテンシが原因でテーブルがロックされることはありません。ただし、テーブルロックが取得されている場合、待機時間が長くなります。
このメカニズムを私よりよく知っている人を引用するには( @ RemusRusan ):
実行が進むと、結果がクライアントプログラムに返されます。行が実行ツリーを「バブル」するとき、最上位のオペレーターは通常、これらの行をネットワークバッファーに書き込み、それらをクライアントに送り返す役割を果たします。結果は最初に中間ストレージ(メモリまたはディスク)に作成されてからクライアントに送り返されるのではなく、作成されたまま(クエリの実行時に)送り返されます。もちろん、結果をクライアントに返すことは、ネットワークフロー制御プロトコルに従います。クライアントが結果をアクティブに消費していない場合(SqlDataReader.Read()を呼び出すなど)、最終的にフロー制御は送信側(実行中のクエリ)をブロックする必要があり、これにより、クエリ。ネットワークフロー制御によって必要なネットワークリソースが解放されるとすぐに、クエリが再開され、より多くの結果が生成されます(実行プランの反復を続行します)。 [ソース]
SQL Serverが提供できるほど速く結果が消費されない場合、クライアントまたはネットワークが原因であっても、ASYNC_NETWORK_IO
蓄積待ち。繰り返しますが、これは取得されたロックには影響せず、保持されている期間のみに影響します。
マークの答えは私の混乱の多くを解消しましたが、待ち時間をエミュレートするためにNetBalancerを使用してこれをテストした後、私の発見を投稿したいと思いました。
ローカルマシンでリモートSQLサーバーを呼び出し、小さなトランザクション内のテーブルでSELECTとINSERTの両方を実行しました。リモートマシンでローカルSQLインスタンスに接続し、WHILEループを使用してsys.dm_tran_locksテーブルを繰り返し反復し、変更および読み取りを行っていたテーブルのロックを探しました。サーバーにNetBalancerをインストールし、それを使用してサーバーのネットワーク接続でのネットワーク遅延をエミュレートしました。
これが私が見つけたものです:
このことから、データがネットワークバッファーに収まる限り、レイテンシは問題にならないと結論づけています。 SQLがネットワークバッファーに大量のデータを配置する必要がある場合、待ち時間によりそのバッファーがバックアップされ、SQLはすべてのクエリ結果をバッファーに配置できるまでテーブルロックを保持します。
高遅延ネットワークを介してMSSQLデータベースを1回呼び出している場合、その遅延のためにテーブルロックが発生しますか?
SQL Serverによってクエリが実行されて完了すると、結果が生成され、出力バッファに配置されてクライアントに送信され、クライアントは出力バッファから結果をフェッチします。 SQL Serverは、クライアントから確認を受信しない限り、クエリによって保持されているロックを解放しません。これはブロッキングを引き起こす可能性があります。
編集:参照できるエヴァン このMSサポート記事
セクション3
対応するクライアントアプリケーションがすべての結果行を完了までフェッチしなかったSPIDが原因のブロッキング
クエリをサーバーに送信した後、すべてのアプリケーションは直ちにすべての結果行をフェッチして完了する必要があります。アプリケーションがすべての結果行をフェッチしない場合、テーブルにロックが残され、他のユーザーをブロックする可能性があります。 SQLステートメントをサーバーに透過的に送信するアプリケーションを使用している場合、アプリケーションはすべての結果行をフェッチする必要があります。そうでない場合(およびそのように構成できない場合)、ブロッキングの問題を解決できない可能性があります。問題を回避するために、動作不良のアプリケーションをレポートデータベースまたは意思決定支援データベースに制限できます。