Compartir a través de


Uso de varios conjuntos de resultados activos (MARS)

SQL Server 2005 introdujo compatibilidad con varios conjuntos de resultados activos (MARS) en aplicaciones que acceden al motor de base de datos. En versiones anteriores de SQL Server, las aplicaciones de base de datos no podían mantener varias instrucciones activas en una conexión. Al usar conjuntos de resultados predeterminados de SQL Server, la aplicación tenía que procesar o cancelar todos los conjuntos de resultados de un lote antes de poder ejecutar cualquier otro lote en esa conexión. SQL Server 2005 introdujo un nuevo atributo de conexión que permite a las aplicaciones tener más de una solicitud pendiente por conexión y, en particular, tener más de un conjunto de resultados predeterminado activo por conexión.

MARS simplifica el diseño de aplicaciones con las siguientes nuevas funcionalidades:

  • Las aplicaciones pueden tener abiertos varios conjuntos de resultados predeterminados y pueden intercalar la lectura de ellos.

  • Las aplicaciones pueden ejecutar otras instrucciones (por ejemplo, INSERT, UPDATE, DELETE y llamadas a procedimientos almacenados) mientras que los conjuntos de resultados predeterminados están abiertos.

Las aplicaciones que usan MARS encontrarán las siguientes directrices beneficiosas:

  • Los conjuntos de resultados predeterminados deben usarse para conjuntos de resultados de corta duración o cortos generados por instrucciones SQL únicas (SELECT, DML con OUTPUT, RECEIVE, READ TEXT, etc.).

  • Los cursores de servidor deben usarse para conjuntos de resultados de larga duración o grandes generados por instrucciones SQL únicas.

  • Lea siempre al final de los resultados de las solicitudes de procedimientos independientemente de si devuelven resultados o no, y para lotes que devuelven varios resultados.

  • Siempre que sea posible, use llamadas API para cambiar las propiedades de conexión y administrar transacciones en preferencia para Transact-SQL instrucciones.

  • En MARS, la suplantación con ámbito de sesión está prohibida mientras se ejecutan lotes simultáneos.

Nota:

De forma predeterminada, la funcionalidad de MARS no está habilitada. Para usar MARS al conectarse a SQL Server con SQL Server Native Client, debe habilitarlo específicamente dentro de una cadena de conexión. Para obtener más información, consulte las secciones Proveedor OLE DB de SQL Server Native Client y Controlador ODBC de SQL Server Native Client, más adelante en este tema.

SQL Server Native Client no limita el número de instrucciones activas en una conexión.

Las aplicaciones típicas que no necesitan tener más de un solo lote de varios estados o procedimientos almacenados que se ejecutan al mismo tiempo se beneficiarán de MARS sin tener que entender cómo se implementa MARS. Sin embargo, las aplicaciones con requisitos más complejos deben tener en cuenta esto.

MARS permite la ejecución intercalada de varias solicitudes dentro de una sola conexión. Es decir, permite que un lote se ejecute y, dentro de su ejecución, permite que se ejecuten otras solicitudes. Sin embargo, tenga en cuenta que MARS se define en términos de intercalación, no en términos de ejecución paralela.

La infraestructura de MARS permite que varios lotes se ejecuten de forma intercalada, aunque la ejecución solo se puede cambiar en puntos bien definidos. Además, la mayoría de las instrucciones deben ejecutarse de forma atómica dentro de un lote. Las instrucciones que devuelven filas al cliente, que a veces se conocen como puntos de rendimiento, pueden intercalar la ejecución antes de finalizar mientras se envían filas al cliente, por ejemplo:

  • Seleccionar

  • TRAER

  • RECIBIR

Cualquier otra instrucción que se ejecute como parte de un procedimiento almacenado o lote debe ejecutarse hasta completarse antes de que la ejecución se pueda cambiar a otras solicitudes de MARS.

La manera exacta en la que los lotes intercalan la ejecución se influyen en una serie de factores y es difícil predecir la secuencia exacta en la que se ejecutarán comandos de varios lotes que contienen puntos de rendimiento. Tenga cuidado de evitar efectos secundarios no deseados debido a la ejecución intercalada de estos lotes complejos.

Evite problemas mediante llamadas API en lugar de Transact-SQL instrucciones para administrar el estado de conexión (SET, USE) y las transacciones (BEGIN TRAN, COMMIT, ROLLBACK) sin incluir estas instrucciones en lotes de varias instrucciones que también contengan puntos de rendimiento y serializando la ejecución de dichos lotes mediante el consumo o cancelación de todos los resultados.

Nota:

Un procedimiento almacenado o por lotes que inicia una transacción manual o implícita cuando MARS está habilitado debe completar la transacción antes de que se cierre el lote. Si no es así, SQL Server revierte todos los cambios realizados por la transacción cuando finalice el lote. SQL Server administra dicha transacción como una transacción de ámbito por lotes. Se trata de un nuevo tipo de transacción introducido en SQL Server 2005 para permitir que se usen procedimientos almacenados bien comportados existentes cuando MARS está habilitado. Para obtener más información sobre las transacciones con ámbito por lotes, vea Instrucciones de transacción (Transact-SQL).

Para obtener un ejemplo de uso de MARS desde ADO, consulte Uso de ADO con SQL Server Native Client.

Proveedor OLE DB de SQL Server Native Client

El proveedor OLE DB de SQL Server Native Client admite MARS mediante la adición de la propiedad de inicialización del origen de datos SSPROP_INIT_MARSCONNECTION, que se implementa en el conjunto de propiedades DBPROPSET_SQLSERVERDBINIT. Además, se ha agregado una nueva palabra clave de cadena de conexión, MarsConn, como se ha agregado. Acepta true o false valores; false es el valor predeterminado.

La propiedad del origen de datos DBPROP_MULTIPLECONNECTIONS el valor predeterminado es VARIANT_TRUE. Esto significa que el proveedor generará varias conexiones para admitir varios objetos de conjunto de filas y comandos simultáneos. Cuando MARS está habilitado, SQL Server Native Client puede admitir varios objetos de conjunto de filas y comandos en una sola conexión, por lo que MULTIPLE_CONNECTIONS se establece en VARIANT_FALSE de forma predeterminada.

Para obtener más información sobre las mejoras realizadas en el conjunto de propiedades DBPROPSET_SQLSERVERDBINIT, vea Propiedades de inicialización y autorización.

Ejemplo del proveedor OLE DB de SQL Server Native Client

En este ejemplo, se crea un objeto de origen de datos mediante el proveedor OLE DB nativo de SQL Server y MARS se habilita mediante la propiedad DBPROPSET_SQLSERVERDBINIT establecida antes de crear el objeto de sesión.

#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);  

Controlador ODBC de SQL Server Native Client

El controlador ODBC de SQL Server Native Client admite MARS mediante adiciones a las funciones SQLSetConnectAttr y SQLGetConnectAttr . SQL_COPT_SS_MARS_ENABLED se ha agregado para aceptar SQL_MARS_ENABLED_YES o SQL_MARS_ENABLED_NO, con SQL_MARS_ENABLED_NO siendo el valor predeterminado. Además, se ha agregado una nueva palabra clave de cadena de conexión, Mars_Connection, como se ha agregado. Acepta valores "sí" o "no"; "no" es el valor predeterminado.

Ejemplo del controlador ODBC de SQL Server Native Client

En este ejemplo, la función SQLSetConnectAttr se usa para habilitar MARS antes de llamar a la función SQLDriverConnect para conectar la base de datos. Una vez realizada la conexión, se llama a dos funciones sqlExecDirect para crear dos conjuntos de resultados independientes en la misma conexión.

#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);  

Véase también

Características de SQL Server Native Client
Uso de conjuntos de resultados predeterminados de SQL Server