Language

複数のアクティブな結果セットの有効化

複数のアクティブな結果セット (MARS : Multiple Active Result Set) は、SQL Server で動作する機能であり、複数のバッチを単一の接続で実行することができます。 SQL Server で使用できるように MARS が有効になっているときは、使用中の各コマンド オブジェクトは接続にセッションを追加します。

注

単一の MARS セッションは、MARS 用に 1 つの論理接続を開いた後、アクティブな各コマンドにつき 1 つの論理接続を開きます。

接続文字列で MARS を有効または無効にする

注

次の接続文字列では、SQL Server に含まれるサンプル AdventureWorks データベースを使用します。 指定されている接続文字列は、データベースが MSSQL1 という名前のサーバーにインストールされているものとします。 実際の環境では必要に応じて接続文字列を変更してください。

既定では、MARS 機能は無効になっています。 これは、接続文字列に "MultipleActiveResultSets=True" キーワード ペアを追加することによって有効にできます。 "True" は、MARS を有効にするための唯一の有効な値です。 次の例は、SQL Server のインスタンスに接続する方法、および MARS を有効にすることを指定する方法を示しています。

Dim connectionString As String = "..." & _
    "MultipleActiveResultSets=True"
string connectionString = "..." +
    "MultipleActiveResultSets=True";

MARS は、接続文字列に "MultipleActiveResultSets=False" キーワード ペアを追加することによって無効にできます。 "False" は、MARS を無効にするための唯一の有効な値です。

MARS の使用に関する特記事項

一般に、MARS の有効な接続を使用するために、既存のアプリケーションを修正する必要はありません。 ただし、MARS 機能をご自分のアプリケーションで使用する場合、次の特記事項について理解しておく必要があります。

ステートメント インタリーブ

MARS 操作は、サーバー上で同期して実行されます。 SELECT および BULK INSERT ステートメントのステートメントのインターリーブが許可されます。 ただし、データ操作言語 (DML) およびデータ定義言語 (DDL) ステートメントはアトミックに実行されます。 アトミック バッチの実行中にステートメントを実行しようとすると、すべてブロックされます。 サーバーでの並列実行は MARS 機能ではありません。

MARS 接続の下で 2 つのバッチが送信され、そのうちの 1 つが SELECT ステートメントを含み、もう 1 つは DML ステートメントを含む場合、DML は SELECT ステートメントの実行中に実行を開始できます。 ただし、DML ステートメントが完了するまで、SELECT ステートメントは先に進めません。 両方のステートメントが同じトランザクションで実行されている場合、 SELECT ステートメントの実行開始後に DML ステートメントによって行われた変更は、読み取り操作には表示されません。

SELECT ステートメント内の WAITFOR ステートメントは、待機中、つまり最初の行が生成されるまではトランザクションを生成しません。 これは、WAITFOR ステートメントが待機中の場合、同じ接続内では他のどのバッチも実行できないことを示しています。

MARS セッションのキャッシュ

MARS を有効にして接続が開くと、プロバイダーによって論理セッションが作成され、オーバーヘッドが増加します。 このオーバーヘッドを減らすために、 SqlClient は接続あたり最大 10 の MARS セッションをキャッシュします。 制限はユーザーが変更できるものではありません 制限に達すると、プロバイダーはエラーなしで新しいセッションを作成します。 キャッシュとそのセッションは、接続間で共有されません。 使用後、キャッシュがいっぱいでない限り、セッションはキャッシュに戻ります。キャッシュがいっぱいの場合、プロバイダーはセッションを閉じます。 キャッシュされたセッションは期限切れになりません。接続を破棄すると、プロバイダーはそれらをクリーンアップします。 アプリケーションにセッションが必要な場合は、プロバイダーはキャッシュにデータを格納します。

スレッド セーフ

MARS 操作は、スレッド セーフではありません。

接続プール

MARS の有効な接続は、その他の接続と同様にまとめて管理されます。 アプリケーションが 2 つの接続を開き、その一方は MARS が有効で他方は MARS が無効になっている場合、それら 2 つの接続は別々のプールに入れられます。 詳しくは、「SQL Server の接続プール (ADO.NET)」をご覧ください。

SQL Server のバッチ実行環境

接続を開くとき、既定の環境が定義されます。 その後、この環境が論理 MARS セッションにコピーされます。

バッチ実行環境には、次のコンポーネントが含まれています。

  • オプション ( ANSI_NULLS、 DATE_FORMAT、 LANGUAGE、 TEXTSIZEなど) を設定する

  • セキュリティ コンテキスト (ユーザー/アプリケーション ロール)

  • データベース コンテキスト (現在のデータベース)

  • 実行状態変数 ( @@ERROR、 @@ROWCOUNT、 @@FETCH_STATUS@@IDENTITYなど)

  • 最上位レベルの一時テーブル

MARS では、既定の実行環境が接続に関連付けられています。 所定の接続で実行を開始する新しいバッチは、いずれも既定の環境のコピーを受け取ります。 特定のバッチのもとでコードが実行された場合は、常に環境に加えられたすべての変更がその特定のバッチにスコープ指定されます。 実行が完了すると、実行の設定は既定の環境にコピーされます。 単一のバッチが複数のコマンドを発行し、それらが同じトランザクションで連続して実行される場合、そのセマンティクスは、以前のクライアントやサーバーを含む接続で公開されているときのセマンティクスと同じです。

並列実行

MARS は、アプリケーション内で複数の接続に対するすべての要件を削除するようには設計されていません。 あるアプリケーションで、サーバーに対するコマンドの真の並列実行が必要な場合は、複数の接続を使用する必要があります。

たとえば、次のようなシナリオがあるとします。 結果セットを処理するためのコマンド オブジェクトと、データを更新するための別のコマンド オブジェクトの 2 つが作成されます。これらは、MARS 経由で共通の接続を共有します。 最初のコマンド オブジェクトの結果をすべて読み取るまで、Transaction. による最初のコマンド オブジェクトの結果をすべて読み取るまで、Commit による更新に失敗し、次の例外が発生します。

メッセージ:トランザクション コンテキストを他のセッションが使用中です。

ソース: .NET SqlClient Data Provider

予想される: (null)

受信: Microsoft.Data.SqlClient.SqlException

このシナリオに対応するには、次の 3 つの方法があります。

  1. リーダーが作成された後にトランザクションを開始し、それがトランザクションの一部にならないようにします。 それにより、すべての更新が独自のトランザクションになります。

  2. リーダーを閉じた後ですべての作業をコミットします。 この場合は、大量の更新バッチが生成される可能性があります。

  3. MARS を使用せず、代わりに MARS が導入される以前に行っていたように、コマンド オブジェクトごとに別々の接続を使用します。

MARS サポートの検出

アプリケーションは、SqlConnection.ServerVersion の値を読み取って MARS サポートを確認することができます。 SQL Server 2005 のメジャー番号は 9、SQL Server 2008 のメジャー番号は 10 です。

関連項目