複数のアクティブな結果セット (MARS) の使用Using Multiple Active Result Sets (MARS)

適用対象: yesSQL Server yesAzure SQL Database yesAzure Synapse Analytics (SQL DW) yesParallel Data Warehouse APPLIES TO: yesSQL Server yesAzure SQL Database yesAzure Synapse Analytics (SQL DW) yesParallel Data Warehouse

SQL Server 2005 (9.x)SQL Server 2005 (9.x) では、データベース エンジンDatabase Engine にアクセスするアプリケーションで複数のアクティブな結果セット (MARS) がサポートされるようになりました。introduced support for multiple active result sets (MARS) in applications accessing the データベース エンジンDatabase Engine. 以前のバージョンの SQL ServerSQL Server では、データベース アプリケーションは 1 つの接続で複数のアクティブなステートメントを保持できませんでした。In earlier versions of SQL ServerSQL Server, database applications could not maintain multiple active statements on a connection. SQL ServerSQL Server の既定の結果セットを使用しているときは、アプリケーションはその接続で他のバッチを実行する前に、1 つのバッチのすべての結果セットを処理するか、取り消す必要がありました。When using SQL ServerSQL Server default result sets, the application had to process or cancel all result sets from one batch before it could execute any other batch on that connection. SQL Server 2005 (9.x)SQL Server 2005 (9.x) では新しい接続属性が導入され、アプリケーションは接続ごとに複数の要求を保留中にできるだけでなく、接続ごとに複数のアクティブな既定の結果セットを保持できるようになりました。introduced a new connection attribute that allows applications to have more than one pending request per connection, and in particular, to have more than one active default result set per connection.

MARS によって、次の新しい機能を使用したアプリケーションのデザインが簡素化されます。MARS simplifies application design with the following new capabilities:

  • アプリケーションは、既定の結果セットを複数開くことができ、複数の既定の結果セットからの読み取りをインターリーブすることができます。Applications can have multiple default result sets open and can interleave reading from them.

  • アプリケーションは既定の結果セットを開いたまま、他のステートメント (INSERT、UPDATE、DELETE、ストアド プロシージャ呼び出しなど) を実行できます。Applications can execute other statements (for example, INSERT, UPDATE, DELETE, and stored procedure calls) while default result sets are open.

MARS を使用するアプリケーションについては、次のガイドラインを参照してください。Applications using MARS will find the following guidelines beneficial:

  • 1 つの SQL ステートメント (SELECT、OUTPUT を伴う DML、RECEIVE、READ TEXT など) で生成される結果セットが短期間しか有効でない場合や結果セットが小さい場合は、既定の結果セットを使用します。Default results sets should be used for short lived or short result sets generated by single SQL statements (SELECT, DML with OUTPUT, RECEIVE, READ TEXT, and so on).

  • 1 つの SQL ステートメントで生成される結果セットが長期間有効な場合や結果セットが大きくなる場合は、サーバー カーソルを使用します。Server cursors should be used for longer lived or large result sets generated by single SQL statements.

  • 結果を返すかどうかにかかわらず手続き型の要求の場合、および複数の結果を返すバッチの場合、常に、結果の最後まで読み取ります。Always read to the end of results for procedural requests regardless of whether they return results or not, and for batches that return multiple results.

  • 接続プロパティの変更やトランザクションの管理には、できるだけ Transact-SQLTransact-SQL ステートメントではなく API 呼び出しを優先して使用します。Wherever possible, use API calls to change connection properties and manage transactions in preference to Transact-SQLTransact-SQL statements.

  • MARS では、複数のバッチが同時に実行されている間、セッション スコープの権限の借用が禁止されます。In MARS, session-scoped impersonation is prohibited while concurrent batches are running.


既定では、MARS 機能はドライバーによって有効になっていません。By default, MARS functionality is not enabled by the driver. SQL ServerSQL Server Native Client を使用して SQL ServerSQL Server に接続するときに MARS を使用するには、接続文字列内で MARS を明示的に有効にする必要があります。To use MARS when connecting to SQL ServerSQL Server with SQL ServerSQL Server Native Client, you must specifically enable MARS within a connection string. ただし、アプリケーションが MARS をサポートしていることをアプリケーションが検出した場合、既定では MARS が有効になることがあります。However, some applications may enable MARS by default, if the application detects that the driver supports MARS. これらのアプリケーションでは、必要に応じて接続文字列の MARS を無効にすることができます。For these applications, you can disable MARS in the connection string as needed. 詳細については、この後の「SQL ServerSQL Server Native Client OLE DB プロバイダー」と「SQL ServerSQL Server Native Client ODBC ドライバー」を参照してください。For more information, see the SQL ServerSQL Server Native Client OLE DB provider and SQL ServerSQL Server Native Client ODBC driver sections, later in this topic.

SQL ServerSQL Server Native Client では、接続でのアクティブなステートメントの数は制限されません。Native Client does not limit the number of active statements on a connection.

複数ステートメントのバッチまたはストアドプロシージャを同時に実行する必要がない一般的なアプリケーションでは、mars の実装方法を理解しなくても、MARS の利点が得られます。Typical applications which do not need to have more than a single multi-statement batch or stored procedure executing at the same time will benefit from MARS without having to understand how MARS is implemented. ただし、より複雑な要件のアプリケーションでは、MARS の実装方法を考慮する必要があります。However, applications with more complex requirements do need to take account of this.

MARS では、1 つの接続内で複数の要求の実行をインターリーブできます。MARS enables the interleaved execution of multiple requests within a single connection. つまり、1 つのバッチを実行し、その実行内で他の要求を実行できます。That is, it allows a batch to run, and within its execution, it allows other requests to execute. ただし、MARS では並列実行が行われるのではなく、複数の実行がインターリーブされることに注意してください。Note, however, that MARS is defined in terms of interleaving, not in terms of parallel execution.

MARS のインフラストラクチャでは、複数のバッチがインターリーブ方式で実行されますが、実行の切り替えは明確に定義された時点でしか行われません。The MARS infrastructure allows multiple batches to execute in an interleaved fashion, though execution can only be switched at well defined points. また、ほとんどのステートメントはバッチ内で自動的に実行される必要があります。In addition, most statements must run atomically within a batch. クライアントに行を返すステートメント ( yield ポイントと呼ばれることもあります) は、次の例のように、行がクライアントに送信されている間、完了前に実行をインターリーブすることができます。Statements which return rows to the client, which are sometimes referred to as yield points, are allowed to interleave execution before completion while rows are being sent to the client, for example:




ストアド プロシージャまたはバッチの一部として実行されるその他のステートメントはいずれも、他の MARS 要求に切り替えられる前に実行を完了する必要があります。Any other statements that are executed as part of a stored procedure or batch must run to completion before execution can be switched to other MARS requests.

バッチがどのようにインターリーブ実行されるかは、さまざまな要因の影響を受けます。そのため、呼び出しポイントを含む複数のバッチからのコマンドが実行されるときに、正確なシーケンスを予測することは困難です。The exact manner in which batches interleave execution is influenced by a number of factors, and it is difficult to predict the exact sequence in which commands from multiple batches that contain yield points will be executed. このような複雑なバッチをインターリーブ実行したときに、好ましくない影響が発生しないように注意してください。Be careful to avoid unwanted side effects due to interleaved execution of such complex batches.

このような問題を回避するために、接続状態 (SET、USE) やトランザクション (BEGIN TRAN、COMMIT、ROLLBACK) を管理する場合は、Transact-SQLTransact-SQL ステートメントではなく API 呼び出しを使用します。このとき、複数のステートメントで構成されるバッチに呼び出しポイントも含まれている場合、接続状態やトランザクションを管理するステートメントを含めないようにします。さらに、このようなバッチでは、すべての結果を処理するか、残りを取り消すことによって、実行を順番に行います。Avoid problems by using API calls rather than Transact-SQLTransact-SQL statements to manage connection state (SET, USE) and transactions (BEGIN TRAN, COMMIT, ROLLBACK) by not including these statements in multi-statement batches that also contain yield points, and by serializing execution of such batches by consuming or canceling all results.


MARS が有効なときにトランザクションを手動または暗黙に開始するバッチやストアド プロシージャでは、バッチが終了する前にトランザクションを完了する必要があります。A batch or stored procedure which starts a manual or implicit transaction when MARS is enabled must complete the transaction before the batch exits. トランザクションを完了しないと、SQL ServerSQL Server はバッチの終了時にトランザクションによって行われたすべての変更をロールバックします。If it does not, SQL ServerSQL Server rolls back all changes made by the transaction when the batch finishes. このようなトランザクションは、SQL ServerSQL Server によってバッチスコープのトランザクションとして管理されます。Such a transaction is managed by SQL ServerSQL Server as a batch-scoped transaction. これは SQL Server 2005 (9.x)SQL Server 2005 (9.x) で導入された新しい形式のトランザクションで、MARS が有効なときに、既存の適切に動作するストアド プロシージャを使用できるようになります。This is a new type of transaction introduced in SQL Server 2005 (9.x)SQL Server 2005 (9.x) to enable existing well-behaved stored procedures to be used when MARS is enabled. バッチスコープのトランザクションの詳細については、「トランザクションステートメント(transact-sql)」を参照してください。For more information about batch-scoped transactions, see Transaction Statements (Transact-SQL).

ADO から MARS を使用する例については、「 USING ado with SQL Server Native Client」を参照してください。For an example of using MARS from ADO, see Using ADO with SQL Server Native Client.

インメモリ OLTPIn-Memory OLTP

インメモリ OLTP では、クエリとネイティブコンパイルストアドプロシージャを使用した MARS がサポートされます。In-memory OLTP supports MARS using queries and natively compiled stored procedures. MARS を使用すると、新しい結果セットから行をフェッチする要求を送信する前に、各結果セットを完全に取得しなくても、複数のクエリからデータを要求することができます。MARS enables requesting data from multiple queries without the need to completely retrieve each result set before sending a request to fetch rows from a new result set. 複数の開いている結果セットから正常に読み取るには、MARS が有効な接続を使用する必要があります。To successfully read from multiple open result sets you must use a MARS enabled connection.

MARS は既定で無効になっているため、接続文字列に MultipleActiveResultSets=True を追加して明示的に有効にする必要があります。MARS is disabled by default so you must explicitly enable it by adding MultipleActiveResultSets=True to a connection string. 次の例は、SQL Server のインスタンスに接続し、MARS が有効になっていることを指定する方法を示しています。The following example demonstrates how to connect to an instance of SQL Server and specify that MARS is enabled:

Data Source=MSSQL; Initial Catalog=AdventureWorks; Integrated Security=SSPI; MultipleActiveResultSets=True  

インメモリ OLTP を使用する MARS は、SQL エンジンの残りの部分では基本的に MARS と同じです。MARS with In-Memory OLTP is essentially the same as MARS in the rest of the SQL engine. 次に、メモリ最適化テーブルとネイティブコンパイルストアドプロシージャで MARS を使用する場合の相違点を示します。The following lists the differences when using MARS in memory-optimized tables and natively compiled stored procedures.

MARS とメモリ最適化テーブルMARS and memory-optimized tables

MARS が有効になっている接続を使用する場合、ディスクベーステーブルとメモリ最適化テーブルの違いは次のとおりです。The following are the differences between disk-based and memory-optimized tables when using a MARS enabled connection:

  • 2つのステートメントで同じ対象オブジェクト内のデータを変更できますが、両方が同じレコードを変更しようとすると、書き込み/書き込みの競合によって新しい操作が失敗します。Two statements can modify data in the same target object but if they both attempt to modify the same record a write-write conflict will cause the new operation to fail. ただし、両方の操作で異なるレコードが変更された場合、操作は成功します。However, if both operations modify different records, the operations will succeed.

  • 各ステートメントはスナップショット分離で実行されるため、新しい操作では既存のステートメントによって行われた変更を表示できません。Each statement runs under SNAPSHOT isolation so new operations cannot see changes made by the existing statements. 同時実行ステートメントが同じトランザクションで実行される場合でも、SQL エンジンは、相互に分離されたステートメントごとにバッチスコープトランザクションを作成します。Even if the concurrent statements are executed under the same transaction the SQL engine creates batch-scoped transactions for each statement that are isolated from each other. ただし、バッチスコープのトランザクションは同時にバインドされるため、1つのバッチスコープトランザクションのロールバックは、同じバッチ内の他のトランザクションに影響を及ぼします。However, batch-scoped transactions are still bound together so rollback of one batch-scoped transaction affects other ones in the same batch.

  • DDL 操作はユーザートランザクションでは許可されないため、すぐに失敗します。DDL operations are not allowed in user transactions so they will immediately fail.

MARS およびネイティブ コンパイル ストアド プロシージャMARS and natively compiled stored procedures

ネイティブコンパイルストアドプロシージャは、MARS が有効になっている接続で実行でき、yield ポイントが検出された場合にのみ実行を別のステートメントにすることができます。Natively compiled stored procedures can run in MARS enabled connections and can yield execution to another statement only when a yield point is encountered. Yield ポイントには SELECT ステートメントが必要です。これは、ネイティブコンパイルストアドプロシージャ内のステートメントであり、別のステートメントを実行することができます。A yield point requires a SELECT statement, which is the only statement within a natively compiled stored procedure that can yield execution to another statement. SELECT ステートメントが生成されないプロシージャ内に存在しない場合は、他のステートメントが開始される前に、そのステートメントが完了するまで実行されます。If a SELECT statement is not present in the procedure it will not yield, it will run to completion before other statements begin.

MARS とインメモリ OLTP のトランザクションMARS and In-memory OLTP transactions

インターリーブされたステートメントおよびアトミックブロックによって行われた変更は、相互に分離されます。Changes made by statements and atomic blocks that are interleaved are isolated from each other. たとえば、1つのステートメントまたは atomic ブロックでいくつかの変更が行われた後、別のステートメントに対して実行が生成された場合、新しいステートメントでは、最初のステートメントによって行われた変更は表示されません。For example, if one statement or atomic block makes some changes, and then yields execution to another statement, the new statement will not see changes made by the first statement. また、最初のステートメントの実行が再開されても、他のステートメントによって行われた変更は表示されません。In addition, when first statement resumes execution, it will not see any changes made by any other statements. ステートメントでは、ステートメントが開始される前に完了してコミットされた変更のみが表示されます。Statements will only see changes that are finished and committed before the statement starts.

BEGIN TRANSACTION ステートメントを使用して、現在のユーザートランザクション内で新しいユーザートランザクションを開始できます。これは相互運用モードでのみサポートされているので、BEGIN TRANSACTION は T-sql ステートメントからのみ呼び出すことができ、ネイティブにコンパイルされたストアドからは呼び出せません。作業.Save TRANSACTION またはトランザクションへの API 呼び出しを使用して、トランザクションにセーブポイントを作成できます。セーブポイントにロールバックするには、(save_point_name) を保存します。A new user transaction can be started within the current user transaction using the BEGIN TRANSACTION statement - this is supported only in interop mode so the BEGIN TRANSACTION can only be called from a T-SQL statement, and not from within a natively compiled stored procedure.You can create a save point in a transaction using SAVE TRANSACTION or an API call to transaction.Save(save_point_name) to rollback to the savepoint. この機能は、ネイティブコンパイルストアドプロシージャ内ではなく、T-sql ステートメントからのみ有効です。This feature is also enabled only from T-SQL statements, and not from within natively compiled stored procedures.

MARS インデックスと列ストアインデックスMARS and columnstore indexes

SQL Server (2016 以降) では、列ストアインデックスを持つ MARS がサポートされます。SQL Server (starting with 2016) supports MARS with columnstore indexes. SQL Server 2014 では、列ストア インデックスに読み取り専用で接続するために MARS が使用されます。SQL Server 2014 uses MARS for read-only connections to tables with a columnstore index. ただし、SQL Server 2014 では、列ストア インデックスを含むテーブルで DML (データ操作言語) を同時操作するとき、MARS を利用できません。However, SQL Server 2014 does not support MARS for concurrent data manipulation language (DML) operations on a table with a columnstore index. その場合、SQL Server は接続を強制終了し、トランザクションを中止します。When this occurs, SQL Server will terminate the connections and abort the transactions. SQL Server 2012 には読み取り専用の列ストアインデックスがあり、MARS は適用されません。SQL Server 2012 has read-only columnstore indexes and MARS does not apply to them.

SQL Server Native Client OLE DB プロバイダーSQL Server Native Client OLE DB Provider

SQL ServerSQL Server Native Client OLE DB プロバイダーは、DBPROPSET_SQLSERVERDBINIT プロパティセットに実装されている SSPROP_INIT_MARSCONNECTION データソース初期化プロパティを追加することによって、MARS をサポートしています。The SQL ServerSQL Server Native Client OLE DB provider supports MARS through the addition of the SSPROP_INIT_MARSCONNECTION data source initialization property, which is implemented in the DBPROPSET_SQLSERVERDBINIT property set. また、新しい接続文字列のキーワードとして MarsConn が追加されました。In addition, a new connection string keyword, MarsConn, as been added. Trueまたはfalseの値を受け取ります。既定値はfalseです。It accepts true or false values; false is the default.

データ ソース プロパティ DBPROP_MULTIPLECONNECTIONS の既定値は VARIANT_TRUE です。The data source property DBPROP_MULTIPLECONNECTIONS defaults to VARIANT_TRUE. これは、複数の同時実行コマンドや行セット オブジェクトをサポートするために、プロバイダーが複数の接続を起動することを意味しています。This means the provider will spawn multiple connections in order to support multiple concurrent command and rowset objects. MARS を有効にすると SQL ServerSQL Server Native Client は、1つの接続で複数のコマンドと行セットオブジェクトをサポートできるため、MULTIPLE_CONNECTIONS は既定で VARIANT_FALSE に設定されます。When MARS is enabled, SQL ServerSQL Server Native Client can support multiple command and rowset objects on a single connection, so MULTIPLE_CONNECTIONS is set to VARIANT_FALSE by default.

DBPROPSET_SQLSERVERDBINIT プロパティセットに対する拡張機能の詳細については、「初期化プロパティと承認プロパティ」を参照してください。For more information about enhancements made to the DBPROPSET_SQLSERVERDBINIT property set, see Initialization and Authorization Properties.

SQL Server Native Client OLE DB プロバイダーの例SQL Server Native Client OLE DB Provider Example

この例では、SQL ServerSQL Server のネイティブ OLE DB プロバイダーを使用してデータソースオブジェクトを作成し、セッションオブジェクトを作成する前に DBPROPSET_SQLSERVERDBINIT プロパティセットを使用して MARS を有効にします。In this example, a data source object is created using the SQL ServerSQL Server Native OLE DB provider, and MARS is enabled using the DBPROPSET_SQLSERVERDBINIT property set before the session object is created.

#include <sqlncli.h>  
IDBInitialize *pIDBInitialize = NULL;  
IDBCreateSession *pIDBCreateSession = NULL;  
IDBProperties *pIDBProperties = NULL;  
// Create the data source object.  
hr = CoCreateInstance(CLSID_SQLNCLI10, NULL,  
hr = pIDBInitialize->QueryInterface(IID_IDBProperties, (void**)&pIDBProperties);  
// Set the MARS property.  
// The following is necessary since MARS is off by default.  
rgPropMARS.dwStatus = DBPROPSTATUS_OK;  
rgPropMARS.colid = DB_NULLID;  
V_VT(&(rgPropMARS.vValue)) = VT_BOOL;  
V_BOOL(&(rgPropMARS.vValue)) = VARIANT_TRUE;  
// Create the structure containing the properties.  
PropSet.rgProperties = &rgPropMARS;  
PropSet.cProperties = 1;  
// Get an IDBProperties pointer and set the initialization properties.  
pIDBProperties->SetProperties(1, &PropSet);  
// Initialize the data source object.  
hr = pIDBInitialize->Initialize();  
//Create a session object from a data source object.  
IOpenRowset * pIOpenRowset = NULL;  
hr = IDBInitialize->QueryInterface(IID_IDBCreateSession, (void**)&pIDBCreateSession));  
hr = pIDBCreateSession->CreateSession(  
   NULL,             // pUnkOuter  
   IID_IOpenRowset,  // riid  
  &pIOpenRowset ));  // ppSession  
// Create a rowset with a firehose mode cursor.  
IRowset *pIRowset = NULL;  
DBPROP rgRowsetProperties[2];  
// To get a firehose mode cursor request a   
// forward only read only rowset.  
rgRowsetProperties[0].dwPropertyID = DBPROP_IRowsetLocate;  
rgRowsetProperties[0].dwOptions = DBPROPOPTIONS_REQUIRED;  
rgRowsetProperties[0].dwStatus = DBPROPSTATUS_OK;  
rgRowsetProperties[0].colid = DB_NULLID;  
rgRowsetProperties[0].vValue.vt = VARIANT_BOOL;  
rgRowsetProperties[0].vValue.boolVal = VARIANT_FALSE;  
rgRowsetProperties[1].dwPropertyID = DBPROP_IRowsetChange;  
rgRowsetProperties[1].dwOptions = DBPROPOPTIONS_REQUIRED;  
rgRowsetProperties[1].dwStatus = DBPROPSTATUS_OK;  
rgRowsetProperties[1].colid = DB_NULLID;  
rgRowsetProperties[1].vValue.vt = VARIANT_BOOL;  
rgRowsetProperties[1].vValue.boolVal = VARIANT_FALSE;  
DBPROPSET rgRowsetPropSet[1];  
rgRowsetPropSet[0].rgProperties = rgRowsetProperties  
rgRowsetPropSet[0].cProperties = 2  
rgRowsetPropSet[0].guidPropertySet = DBPROPSET_ROWSET;  
hr = pIOpenRowset->OpenRowset (NULL,  

SQL Server Native Client ODBC ドライバーSQL Server Native Client ODBC Driver

SQL ServerSQL Server Native Client ODBC ドライバーでは、 SQLSetConnectAttrおよびSqlgetconnectattr関数への追加によって MARS がサポートされています。The SQL ServerSQL Server Native Client ODBC driver supports MARS through additions to the SQLSetConnectAttr and SQLGetConnectAttr functions. SQL_COPT_SS_MARS_ENABLED が追加され、SQL_MARS_ENABLED_YES または SQL_MARS_ENABLED_NO を受け取ります。既定値は SQL_MARS_ENABLED_NO です。SQL_COPT_SS_MARS_ENABLED has been added to accept either SQL_MARS_ENABLED_YES or SQL_MARS_ENABLED_NO, with SQL_MARS_ENABLED_NO being the default. さらに、新しい接続文字列キーワードMars_Connectionが追加されました。In addition, a new connection string keyword, Mars_Connection, as been added. このキーワードは、"yes" と "no" を値として受け取ります。既定値は "no" です。It accepts "yes" or "no" values; "no" is the default.

SQL Server Native Client ODBC ドライバーの例SQL Server Native Client ODBC Driver Example

この例では、 SQLSetConnectAttr関数を使用して、 SQLDriverConnect関数を呼び出してデータベースに接続する前に、MARS を有効にします。In this example, the SQLSetConnectAttr function is used to enable MARS before calling the SQLDriverConnect function to connect the database. 接続が確立されると、2つのSQLExecDirect関数が呼び出され、同じ接続に2つの異なる結果セットが作成されます。Once the connection is made, two SQLExecDirect functions are called to create two separate result sets on the same connection.

#include <sqlncli.h>  
SQLDriverConnect(hdbc, hwnd,   
   "DRIVER=SQL Server Native Client 10.0;  
   SERVER=(local);trusted_connection=yes;", SQL_NTS, szOutConn,   
SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt1);  
SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &hstmt2);  
// The 2nd execute would have failed with connection busy error if  
// MARS were not enabled.  
SQLExecDirect(hstmt1, L"SELECT * FROM Authors", SQL_NTS);  
SQLExecDirect(hstmt2, L"SELECT * FROM Titles", SQL_NTS);  
// Result set processing can interleave.  

参照See Also

SQL Server Native Client の機能 SQL Server Native Client Features
SQL Server の既定の結果セットの使用Using SQL Server Default Result Sets