Freigeben über


Verwenden von Multiple Active Result Sets (MARS)

SQL Server 2005 wurde unterstützung für mehrere aktive Resultsets (MARS) in Anwendungen eingeführt, die auf die Datenbank-Engine zugreifen. In früheren Versionen von SQL Server konnten Datenbankanwendungen nicht mehrere aktive Anweisungen über eine Verbindung verwalten. Beim Verwenden von SQL Server-Standardresultsets musste die Anwendung alle Resultsets aus einem Batch verarbeiten oder abbrechen, bevor ein anderer Batch auf dieser Verbindung ausgeführt werden konnte. SQL Server 2005 wurde ein neues Verbindungsattribute eingeführt, mit dem Anwendungen mehr als eine ausstehende Anforderung pro Verbindung und insbesondere mehr als ein aktives Standardergebnissatz pro Verbindung haben können.

MARS vereinfacht den Anwendungsentwurf mit den folgenden neuen Fähigkeiten:

  • Anwendungen können mehrere Standardresultsets geöffnet haben und die Lesevorgänge daraus verschachteln.

  • Anwendungen können bei geöffneten Standardresultsets andere Anweisungen ausführen (z. B. INSERT, UPDATE, DELETE und Aufrufe gespeicherter Prozeduren).

Für Anwendungen, die MARS verwenden, gelten die folgenden nützlichen Richtlinien:

  • Standardresultsets sollten für kurzlebige oder kurze Resultsets verwendet werden, die durch einzelne SQL-Anweisungen generiert werden (SELECT, DML mit OUTPUT, RECEIVE, READ TEXT usw.).

  • Servercursor sollten für längerlebige oder große Resultsets verwendet werden, die durch einzelne SQL-Anweisungen generierte werden.

  • Lesen Sie bei Batches, die mehrere Ergebnisse zurückgeben, und bei Prozeduranforderungen immer bis zum Ende der Results, unabhängig davon, ob Ergebnisse zurückgeben werden oder nicht.

  • Wo möglich, verwenden Sie anstelle von Transact-SQL-Anweisungen API-Aufrufe, um Verbindungseigenschaften zu ändern und Transaktionen zu verwalten.

  • In MARS wird ein Identitätswechsel im Bereich einer Sitzung verhindert, solange gleichzeitige Batches ausgeführt werden.

Hinweis

Standardmäßig ist die MARS-Funktionalität nicht aktiviert. Um MARS beim Herstellen einer Verbindung mit SQL Server mit SQL Server Native Client zu verwenden, müssen Sie es speziell in einer Verbindungszeichenfolge aktivieren. Weitere Informationen finden Sie in den Abschnitten SQL Server Native Client OLE DB-Anbieter und SQL Server Native Client ODBC-Treiber weiter unten in diesem Thema.

SQL Server Native Client beschränkt nicht die Anzahl aktiver Anweisungen für eine Verbindung.

Typische Anwendungen, bei denen kein Bedarf für mehrere Batches oder gespeicherte Prozeduren aus mehreren gleichzeitig ausgeführten Anweisungen besteht, profitieren von MARS, ohne die Implementierung von MARS verstehen zu müssen. Anwendungen mit komplexeren Anforderungen müssen diese jedoch berücksichtigen.

MARS ermöglicht die verschachtelte Ausführung mehrerer Anforderungen innerhalb einer einzelnen Verbindung. Das bedeutet, dass innerhalb der Ausführung eines Batches eine weitere Anforderung ausgeführt werden kann. Beachten Sie jedoch, dass MARS mit Blick auf Interleaving, nicht die parallele Ausführung definiert ist.

Die MARS-Infrastruktur ermöglicht die verschachtelte Ausführung mehrerer Batches, die Ausführung kann jedoch nur an genau definierten Punkten gewechselt werden. Außerdem müssen die meisten Anweisungen innerhalb eines Batches atomar ausgeführt werden. Anweisungen, die Zeilen an den Client zurückgeben, die manchmal auch als Ertragspunkte bezeichnet werden, können die Ausführung vor Abschluss zwischenspeichern, während Zeilen an den Client gesendet werden, z. B.:

  • SELECT

  • FETCH

  • RECEIVE

Alle anderen Anweisungen, die im Rahmen einer gespeicherten Prozedur oder eines Batches ausgeführt werden, müssen zunächst abgeschlossen werden, ehe die Ausführung zu anderen MARS-Anforderungen umgeschaltet werden kann.

Wie Batches die Ausführung genau verschachteln, hängt von zahlreichen Faktoren ab, und die exakte Ausführungsfolge von Befehlen aus mehreren Batches mit Zwischenergebnispunkten lässt sich nur schwer vorhersagen. Achten Sie darauf, unerwünschte Nebeneffekte aufgrund der verschachtelten Ausführung solcher komplexer Batches zu vermeiden.

Sie vermeiden Probleme, indem Sie den Verbindungsstatus (SET, USE) und Transaktionen (BEGIN TRAN, COMMIT, ROLLBACK) an Stelle von Transact-SQL-Anweisungen mit API-Aufrufen verwalten. Schließen Sie diese Anweisungen zudem nicht in Batches mit mehreren Anweisungen ein, die auch Zwischenergebnispunkte enthalten, und serialisieren Sie die Ausführung solcher Batches durch Verarbeitung oder Abbruch aller Ergebnisse.

Hinweis

Ein Batch oder eine gespeicherte Prozedur, die bei Aktivierung von MARS eine manuelle oder implizite Transaktion startet, muss diese Transaktion vor Ausführung des Batchs abschließen. Andernfalls führt SQL Server nach Abschluss des Batchs einen Rollback für alle von der Transaktion vorgenommenen Änderungen aus. Eine derartige Transaktion wird von SQL Server als Transaktion im Bereich des Batchs verwaltet. Dies ist eine neue Art von Transaktion, die in SQL Server 2005 eingeführt wurde, um die Verwendung vorhandener, gut verhaltener gespeicherter Prozeduren zu ermöglichen, wenn MARS aktiviert ist. Weitere Informationen zu Transaktionen im Bereich des Batches finden Sie unter Transaktionsanweisungen (Transact-SQL).

Ein Beispiel für die Verwendung von MARS aus ADO finden Sie unter Verwenden von ADO mit SQL Server Native Client.

SQL Server Native Client OLE DB-Anbieter

Der SQL Server Native Client OLE DB-Anbieter unterstützt MARS durch das Hinzufügen der SSPROP_INIT_MARSCONNECTION-Datenquelleninitialisierungseigenschaft, die im DBPROPSET_SQLSERVERDBINIT-Eigenschaftssatz implementiert ist. Außerdem wurde ein neues Verbindungszeichenfolgen-Schlüsselwort aufgenommen, MarsConn. Gültige Werte sind true oder false; der Standardwert ist false.

Die Datenquelleneigenschaft DBPROP_MULTIPLECONNECTIONS ist standardmäßig auf VARIANT_TRUE festgelegt. Das bedeutet, der Anbieter erzeugt mehrere Verbindungen, um mehrere gleichzeitige Befehls- und Rowsetobjekte zu unterstützen. Wenn MARS aktiviert ist, können SQL Server Native Client mehrere Befehls- und Rowsetobjekte für eine einzelne Verbindung unterstützen, sodass MULTIPLE_CONNECTIONS standardmäßig auf VARIANT_FALSE festgelegt ist.

Weitere Informationen zu Verbesserungen am DBPROPSET_SQLSERVERDBINIT-Eigenschaftensatz finden Sie unter Initialisierungs- und Autorisierungseigenschaften.

OLE DB-Anbieter von SQL Server Native Client: Beispiel

In diesem Beispiel wird ein Datenquellenobjekt mit dem SQL Server nativen OLE DB-Anbieter erstellt, und MARS wird mithilfe des DBPROPSET_SQLSERVERDBINIT Eigenschaftensatzes aktiviert, bevor das Sitzungsobjekt erstellt wird.

#include <sqlncli.h>  
  
IDBInitialize *pIDBInitialize = NULL;  
IDBCreateSession *pIDBCreateSession = NULL;  
IDBProperties *pIDBProperties = NULL;  
  
// Create the data source object.  
hr = CoCreateInstance(CLSID_SQLNCLI10, NULL,  
   CLSCTX_INPROC_SERVER,  
   IID_IDBInitialize,   
    (void**)&pIDBInitialize);  
  
hr = pIDBInitialize->QueryInterface(IID_IDBProperties, (void**)&pIDBProperties);  
  
// Set the MARS property.  
DBPROP rgPropMARS;  
  
// The following is necessary since MARS is off by default.  
rgPropMARS.dwPropertyID = SSPROP_INIT_MARSCONNECTION;  
rgPropMARS.dwOptions = DBPROPOPTIONS_REQUIRED;  
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.  
DBPROPSET PropSet;  
PropSet.rgProperties = &rgPropMARS;  
PropSet.cProperties = 1;  
PropSet.guidPropertySet = DBPROPSET_SQLSERVERDBINIT;  
  
// Get an IDBProperties pointer and set the initialization properties.  
pIDBProperties->SetProperties(1, &PropSet);  
pIDBProperties->Release();  
  
// 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;  
VariantInit(&(rgRowsetProperties[0].vValue));  
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;  
VariantInit(&(rgRowsetProperties[1].vValue));  
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,  
   &TableID,  
   NULL,  
   IID_IRowset,  
   1,  
   rgRowsetPropSet  
   (IUnknown**)&pIRowset);  

ODBC-Treiber für SQL Server Native Client

Der SQL Server Native Client ODBC-Treiber unterstützt MARS durch Ergänzungen zu den Funktionen SQLSetConnectAttr und SQLGetConnectAttr. SQL_COPT_SS_MARS_ENABLED wurde hinzugefügt, um entweder SQL_MARS_ENABLED_YES oder SQL_MARS_ENABLED_NO zu akzeptieren. Der Standardwert ist SQL_MARS_ENABLED_NO. Außerdem wurde ein neues Verbindungszeichenfolgen-Schlüsselwort aufgenommen, Mars_Connection. Gültige Werte sind "Ja" oder "Nein", wobei "Nein" die Standardeinstellung ist.

SQL Server Native Client-ODBC-Treiber: Beispiel

In diesem Beispiel wird die SQLSetConnectAttr-Funktion verwendet, um MARS zu aktivieren, bevor die FUNKTION SQLDriverConnect aufgerufen wird, um die Datenbank zu verbinden. Nachdem die Verbindung hergestellt wurde, werden zwei SQLExecDirect-Funktionen aufgerufen, um zwei separate Resultsets für dieselbe Verbindung zu erstellen.

#include <sqlncli.h>  
  
SQLSetConnectAttr(hdbc, SQL_COPT_SS_MARS_ENABLED, SQL_MARS_ENABLED_YES, SQL_IS_UINTEGER);  
SQLDriverConnect(hdbc, hwnd,   
   "DRIVER=SQL Server Native Client 10.0;  
   SERVER=(local);trusted_connection=yes;", SQL_NTS, szOutConn,   
   MAX_CONN_OUT, &cbOutConn, SQL_DRIVER_COMPLETE);  
  
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.  
SQLFetch(hstmt1);  
SQLFetch(hstmt2);  

Weitere Informationen

SQL Server Native Client-Funktionen
Verwenden von SQL Server-Standardresultsets