Agrupación de conexiones de SQL Server (ADO.NET)SQL Server Connection Pooling (ADO.NET)

La conexión a un servidor de bases de datos suele constar de varios pasos que requieren mucho tiempo.Connecting to a database server typically consists of several time-consuming steps. Se debe establecer un canal físico, como un socket o una canalización con nombre, debe tener lugar el protocolo de enlace con el servidor, se debe analizar la información de la cadena de conexión, el servidor debe autenticar la conexión, se deben ejecutar comprobaciones para la inscripción en la transacción actual, etc.A physical channel such as a socket or a named pipe must be established, the initial handshake with the server must occur, the connection string information must be parsed, the connection must be authenticated by the server, checks must be run for enlisting in the current transaction, and so on.

En la práctica, la mayoría de las aplicaciones solamente utilizan unas cuantas configuraciones diferentes para las conexiones.In practice, most applications use only one or a few different configurations for connections. Esto significa que durante la ejecución de la aplicación, muchas conexiones idénticas se abrirán y cerrarán de forma repetida.This means that during application execution, many identical connections will be repeatedly opened and closed. Para minimizar el costo de la apertura de conexiones, ADO.NET usa una técnica de optimización denominada agrupaciónde conexiones.To minimize the cost of opening connections, ADO.NET uses an optimization technique called connection pooling.

La agrupación de conexiones reduce el número de veces que es necesario abrir nuevas conexiones.Connection pooling reduces the number of times that new connections must be opened. El concentrador mantiene la propiedad de la conexión física.The pooler maintains ownership of the physical connection. Para administrar las conexiones, mantiene un conjunto de conexiones activas para cada configuración de conexión dada.It manages connections by keeping alive a set of active connections for each given connection configuration. Cada vez que un usuario llama a Open en una conexión, el agrupador comprueba si hay una conexión disponible en el grupo.Whenever a user calls Open on a connection, the pooler looks for an available connection in the pool. Si hay disponible una conexión agrupada, la devuelve a la persona que llama en lugar de abrir una nueva.If a pooled connection is available, it returns it to the caller instead of opening a new connection. Cuando la aplicación llama a Close en la conexión, el agrupador la devuelve al conjunto agrupado de conexiones activas en lugar de cerrarla.When the application calls Close on the connection, the pooler returns it to the pooled set of active connections instead of closing it. Una vez que la conexión vuelve al grupo, ya está preparada para volverse a utilizar en la siguiente llamada a Open.Once the connection is returned to the pool, it is ready to be reused on the next Open call.

Solo se pueden agrupar conexiones con la misma configuración.Only connections with the same configuration can be pooled. ADO.NET mantiene varios grupos al mismo tiempo, uno para cada configuración.ADO.NET keeps several pools at the same time, one for each configuration. Las conexiones se dividen en grupos por cadena de conexión, y por identidad de Windows si se utiliza seguridad integrada.Connections are separated into pools by connection string, and by Windows identity when integrated security is used. Las conexiones también se agrupan en función de si están incluidas en una transacción.Connections are also pooled based on whether they are enlisted in a transaction. Cuando se usa ChangePassword, la instancia de SqlCredential afecta al grupo de conexiones.When using ChangePassword, the SqlCredential instance affects the connection pool. Distintas instancias de SqlCredential usarán diferentes grupos de conexiones, incluso si el identificador de usuario y la contraseña son iguales.Different instances of SqlCredential will use different connection pools, even if the user ID and password are the same.

La agrupación de conexiones puede mejorar de forma considerable el rendimiento y la escalabilidad de la aplicación.Pooling connections can significantly enhance the performance and scalability of your application. De forma predeterminada, la agrupación de conexiones está habilitada en ADO.NET.By default, connection pooling is enabled in ADO.NET. A menos que la deshabilite explícitamente, el agrupador optimiza las conexiones a medida que se abren y cierran en la aplicación.Unless you explicitly disable it, the pooler optimizes the connections as they are opened and closed in your application. También puede proporcionar varios modificadores de cadena de conexión para controlar el comportamiento de agrupación de conexiones.You can also supply several connection string modifiers to control connection pooling behavior. Para obtener más información, vea "Control de la agrupación de conexiones con palabras clave de cadena de conexión" más adelante en este tema.For more information, see "Controlling Connection Pooling with Connection String Keywords" later in this topic.

Nota

Cuando se habilita la agrupación de conexiones, y si se produce un error de tiempo de expiración u otro error de inicio de sesión, se producirá una excepción y los intentos de conexión posteriores producirán errores durante los cinco segundos siguientes, el "período de bloqueo".When connection pooling is enabled, and if a timeout error or other login error occurs, an exception will be thrown and subsequent connection attempts will fail for the next five seconds, the "blocking period". Si la aplicación intenta conectarse dentro del período de bloqueo, se volverá a producir la primera excepción.If the application attempts to connect within the blocking period, the first exception will be thrown again. Los errores que se produzcan después de que finalice un período de bloqueo darán lugar a nuevos períodos de bloqueo que serán el doble de largos que el período de bloqueo anterior, hasta un máximo de un minuto.Subsequent failures after a blocking period ends will result in a new blocking periods that is twice as long as the previous blocking period, up to a maximum of one minute.

Creación y asignación del grupoPool Creation and Assignment

Cuando se abre una conexión por primera vez, se crea un grupo de conexión basado en un algoritmo de coincidencia exacta que asocia el grupo con la cadena de conexión de la conexión.When a connection is first opened, a connection pool is created based on an exact matching algorithm that associates the pool with the connection string in the connection. Cada grupo de conexión se asocia con una cadena de conexión distinta.Each connection pool is associated with a distinct connection string. Si se abre una nueva conexión y la cadena de conexión no coincide exactamente con un grupo existente, se crea un nuevo grupo.When a new connection is opened, if the connection string is not an exact match to an existing pool, a new pool is created. Las conexiones se agrupan por proceso, por dominio de aplicación, por cadena de conexión y, cuando se utiliza seguridad integrada, por identidad de Windows.Connections are pooled per process, per application domain, per connection string and when integrated security is used, per Windows identity. Las cadenas de conexión también deben ser una coincidencia exacta; las palabras clave indicadas en un orden diferente para la misma conexión se agruparán por separado.Connection strings must also be an exact match; keywords supplied in a different order for the same connection will be pooled separately.

En el siguiente ejemplo con C#, se crean tres nuevos objetos SqlConnection, pero solo se necesitan dos grupos de conexión para administrarlos.In the following C# example, three new SqlConnection objects are created, but only two connection pools are required to manage them. Observe que las cadenas de conexión primera y segunda difieren en el valor asignado a Initial Catalog.Note that the first and second connection strings differ by the value assigned for Initial Catalog.

using (SqlConnection connection = new SqlConnection(  
  "Integrated Security=SSPI;Initial Catalog=Northwind"))  
    {  
        connection.Open();        
        // Pool A is created.  
    }  
  
using (SqlConnection connection = new SqlConnection(  
  "Integrated Security=SSPI;Initial Catalog=pubs"))  
    {  
        connection.Open();        
        // Pool B is created because the connection strings differ.  
    }  
  
using (SqlConnection connection = new SqlConnection(  
  "Integrated Security=SSPI;Initial Catalog=Northwind"))  
    {  
        connection.Open();        
        // The connection string matches pool A.  
    }  

Si no se especifica MinPoolSize en la cadena de conexión o se especifica como cero, las conexiones del grupo se cerrarán tras un período de inactividad.If MinPoolSize is either not specified in the connection string or is specified as zero, the connections in the pool will be closed after a period of inactivity. No obstante, si el MinPoolSize especificado es mayor que cero, el grupo de conexión no se destruye hasta que se descarga el AppDomain y finaliza el proceso.However, if the specified MinPoolSize is greater than zero, the connection pool is not destroyed until the AppDomain is unloaded and the process ends. El mantenimiento de grupos inactivos o vacíos supone una sobrecarga mínima para el sistema.Maintenance of inactive or empty pools involves minimal system overhead.

Nota

El grupo se borra automáticamente cuando se produce un error irrecuperable, como una conmutación por error.The pool is automatically cleared when a fatal error occurs, such as a failover.

Agregar conexionesAdding Connections

Para cada cadena de conexión única se crea un grupo de conexión.A connection pool is created for each unique connection string. Cuando se crea un grupo, se crean y agregan al grupo varios objetos de conexión y se satisface así el requisito de tamaño mínimo del grupo.When a pool is created, multiple connection objects are created and added to the pool so that the minimum pool size requirement is satisfied. Las conexiones se agregan al grupo cuando es necesario, hasta el tamaño máximo del grupo especificado (100 es el valor predeterminado),Connections are added to the pool as needed, up to the maximum pool size specified (100 is the default). y se liberan de nuevo en el grupo cuando se cierran o eliminan.Connections are released back into the pool when they are closed or disposed.

Cuando se solicita un objeto SqlConnection, se obtiene del grupo si se encuentra disponible una conexión que se pueda utilizar.When a SqlConnection object is requested, it is obtained from the pool if a usable connection is available. Una conexión de este tipo debe estar sin utilizar, tener un contexto de transacción coincidente o no estar asociada con ningún contexto de transacción y tener un vínculo válido al servidor.To be usable, a connection must be unused, have a matching transaction context or be unassociated with any transaction context, and have a valid link to the server.

El agrupador de conexiones satisface las solicitudes de conexión al reasignar las conexiones conforme se liberan de nuevo en el grupo.The connection pooler satisfies requests for connections by reallocating connections as they are released back into the pool. Si se ha alcanzado el tamaño máximo del grupo y no hay disponible ninguna conexión que se pueda utilizar, la solicitud se pone en la cola.If the maximum pool size has been reached and no usable connection is available, the request is queued. A continuación, el concentrador intenta reclamar las conexiones hasta que se agota el tiempo de espera (el valor predeterminado es 15 segundos).The pooler then tries to reclaim any connections until the time-out is reached (the default is 15 seconds). Si no puede satisfacer la solicitud antes de que se agote el tiempo de espera de la conexión, se inicia una excepción.If the pooler cannot satisfy the request before the connection times out, an exception is thrown.

Precaución

Se recomienda encarecidamente cerrar siempre la conexión cuando se termine de utilizar para que regrese al grupo.We strongly recommend that you always close the connection when you are finished using it so that the connection will be returned to the pool. Para ello, puede usar los Close métodos o Dispose del Connection objeto o abrir todas las conexiones dentro de una using instrucción de C#, o una Using instrucción de Visual Basic.You can do this using either the Close or Dispose methods of the Connection object, or by opening all connections inside a using statement in C#, or a Using statement in Visual Basic. Es posible que las conexiones que no se cierran explícitamente no se puedan agregar ni puedan regresar al grupo.Connections that are not explicitly closed might not be added or returned to the pool. Para obtener más información, vea Using instruccióno cómo: Desechar un recurso del sistema para Visual Basic.For more information, see using Statement or How to: Dispose of a System Resource for Visual Basic.

Nota

No llame a Close o a Dispose en un objeto Connection, un objeto DataReader o cualquier otro objeto administrado en el método Finalize de la clase.Do not call Close or Dispose on a Connection, a DataReader, or any other managed object in the Finalize method of your class. En un finalizador, libere solo los recursos no administrados que pertenezcan directamente a su clase.In a finalizer, only release unmanaged resources that your class owns directly. Si la clase no dispone de recursos no administrados, no incluya un método Finalize en la definición de clase.If your class does not own any unmanaged resources, do not include a Finalize method in your class definition. Para obtener más información, consulte recolección de elementos no utilizados.For more information, see Garbage Collection.

Para obtener más información sobre los eventos asociados a la apertura y el cierre de conexiones, vea Audit login Event Class y Audit Logout Event Class en la documentación de SQL Server.For more info about the events associated with opening and closing connections, see Audit Login Event Class and Audit Logout Event Class in the SQL Server documentation.

Cómo quitar conexionesRemoving Connections

El agrupador de conexiones quita una conexión del grupo después de haber estado inactiva unos 4-8 minutos o si detecta que se ha roto la conexión con el servidor.The connection pooler removes a connection from the pool after it has been idle for approximately 4-8 minutes, or if the pooler detects that the connection with the server has been severed. Tenga en cuenta que una conexión rota solo puede detectarse después de intentar comunicarse con el servidor.Note that a severed connection can be detected only after attempting to communicate with the server. Si se encuentra que una conexión ya no está conectada al servidor, se marca como no válida.If a connection is found that is no longer connected to the server, it is marked as invalid. Las conexiones no válidas se quitan del grupo de conexión solo cuando se cierran o reclaman.Invalid connections are removed from the connection pool only when they are closed or reclaimed.

Si existe una conexión en un servidor que ha desaparecido, se puede extraer del grupo aunque el agrupador de conexiones no haya detectado la conexión rota y la haya marcado como no válida.If a connection exists to a server that has disappeared, this connection can be drawn from the pool even if the connection pooler has not detected the severed connection and marked it as invalid. El motivo es que la sobrecarga de comprobar que la conexión es aún válida eliminaría los beneficios de tener un concentrador y ocasionaría que se produjera otro viaje de ida y vuelta (round trip) al servidor.This is the case because the overhead of checking that the connection is still valid would eliminate the benefits of having a pooler by causing another round trip to the server to occur. Cuando esto ocurre, el primer intento para usar la conexión detectará que ésta se ha roto y se iniciará una excepción.When this occurs, the first attempt to use the connection will detect that the connection has been severed, and an exception is thrown.

Borrado del grupoClearing the Pool

ADO.net 2,0 presentó dos nuevos métodos para borrar el Grupo: ClearAllPools y ClearPool.ADO.NET 2.0 introduced two new methods to clear the pool: ClearAllPools and ClearPool. ClearAllPools borra los grupos de conexión de un proveedor dado, y ClearPool borra el grupo de conexión que está asociado a una conexión concreta.ClearAllPools clears the connection pools for a given provider, and ClearPool clears the connection pool that is associated with a specific connection. Si en el momento de la llamada se están usando conexiones, se marcan de forma adecuada.If there are connections being used at the time of the call, they are marked appropriately. Cuando se cierran, se descartan en lugar de devolverse al grupo.When they are closed, they are discarded instead of being returned to the pool.

Compatibilidad con transaccionesTransaction Support

Las conexiones se extraen del grupo y se asignan en función del contexto de transacción.Connections are drawn from the pool and assigned based on transaction context. A menos que se especifique Enlist=false en la cadena de conexión, el grupo de conexión garantiza que la conexión está dada de alta en el contexto de Current.Unless Enlist=false is specified in the connection string, the connection pool makes sure that the connection is enlisted in the Current context. Cuando se cierra una conexión y se devuelve al grupo con una transacción System.Transactions dada de alta, se reserva de forma que la siguiente solicitud de ese grupo de conexiones con la misma transacción System.Transactions devolverá la misma conexión, si está disponible.When a connection is closed and returned to the pool with an enlisted System.Transactions transaction, it is set aside in such a way that the next request for that connection pool with the same System.Transactions transaction will return the same connection if it is available. Si se emite dicha solicitud y no hay conexiones agrupadas disponibles, se extrae una conexión de la parte sin transacción del grupo y se le da de alta.If such a request is issued, and there are no pooled connections available, a connection is drawn from the non-transacted part of the pool and enlisted. Si no hay conexiones disponibles en cualquier área del grupo, se crea y da de alta una nueva conexión.If no connections are available in either area of the pool, a new connection is created and enlisted.

Cuando se cierra una conexión, se libera de nuevo en el grupo y en la subdivisión adecuada en función de su contexto de transacción.When a connection is closed, it is released back into the pool and into the appropriate subdivision based on its transaction context. Por lo tanto, puede cerrar la conexión sin generar un error, incluso aunque aún haya pendiente una transacción distribuida.Therefore, you can close the connection without generating an error, even though a distributed transaction is still pending. Esto permite confirmar o anular la transacción distribuida más adelante.This allows you to commit or abort the distributed transaction later.

Control de la agrupación de conexiones con palabras clave de cadena de conexiónControlling Connection Pooling with Connection String Keywords

La propiedad ConnectionString del objeto SqlConnection admite pares clave-valor de cadena de conexión que se pueden utilizar para ajustar el comportamiento de la lógica de agrupación de conexiones.The ConnectionString property of the SqlConnection object supports connection string key/value pairs that can be used to adjust the behavior of the connection pooling logic. Para obtener más información, consulta ConnectionString.For more information, see ConnectionString.

Fragmentación de gruposPool Fragmentation

La fragmentación de grupos es un problema común en muchas aplicaciones web en las que la aplicación puede crear gran cantidad de grupos que no se liberan hasta que finaliza el proceso.Pool fragmentation is a common problem in many Web applications where the application can create a large number of pools that are not freed until the process exits. El resultado es un gran número de conexiones abiertas que consumen memoria, lo que da lugar a un bajo rendimiento.This leaves a large number of connections open and consuming memory, which results in poor performance.

Fragmentación de grupos debido a la seguridad integradaPool Fragmentation Due to Integrated Security

Las conexiones se agrupan de acuerdo con la cadena de conexión y la identidad del usuario.Connections are pooled according to the connection string plus the user identity. Por lo tanto, si utiliza autenticación básica o autenticación de Windows en el sitio web y un inicio de sesión de seguridad integrada, obtendrá un grupo por usuario.Therefore, if you use Basic authentication or Windows Authentication on the Web site and an integrated security login, you get one pool per user. Aunque de esta manera se mejora el rendimiento de las posteriores solicitudes de base de datos de un solo usuario, ese usuario no podrá aprovechar las conexiones realizadas por otros usuarios.Although this improves the performance of subsequent database requests for a single user, that user cannot take advantage of connections made by other users. Además, como resultado habrá una conexión como mínimo por usuario al servidor de bases de datos.It also results in at least one connection per user to the database server. Se trata de un efecto secundario de una determinada arquitectura de aplicaciones web que los desarrolladores deben sopesar frente a los requisitos de seguridad y auditoría.This is a side effect of a particular Web application architecture that developers must weigh against security and auditing requirements.

Fragmentación de grupos debido a muchas bases de datosPool Fragmentation Due to Many Databases

Muchos proveedores de acceso a Internet hospedan varios sitios web en un único servidor.Many Internet service providers host several Web sites on a single server. Puede que utilicen una sola base de datos para confirmar un inicio de sesión de autenticación de formularios y luego abran una conexión a una base de datos específica para ese usuario o grupo de usuarios.They may use a single database to confirm a Forms authentication login and then open a connection to a specific database for that user or group of users. La conexión a la base de datos de autenticación es agrupada y utilizada por todo el mundo.The connection to the authentication database is pooled and used by everyone. Sin embargo, hay un grupo independiente de conexiones con cada base de datos, lo que implica un aumento del número de conexiones con el servidor.However, there is a separate pool of connections to each database, which increase the number of connections to the server.

Este es también un efecto secundario del diseño de la aplicación.This is also a side-effect of the application design. Existe, sin embargo, una forma relativamente sencilla de evitarlo sin comprometer la seguridad cuando se establece conexión con SQL Server.There is a relatively simple way to avoid this side effect without compromising security when you connect to SQL Server. En lugar de realizar una conexión a una base de datos diferente por cada usuario o grupo, realice una conexión a la misma base de datos en el servidor y, a continuación, ejecute la instrucción USE de Transact-SQL para cambiar a la base de datos deseada.Instead of connecting to a separate database for each user or group, connect to the same database on the server and then execute the Transact-SQL USE statement to change to the desired database. En el siguiente fragmento de código se muestra la creación de una conexión inicial con la base de datos master y el cambio a la base de datos deseada especificada en la variable de cadena databaseName.The following code fragment demonstrates creating an initial connection to the master database and then switching to the desired database specified in the databaseName string variable.

' Assumes that command is a valid SqlCommand object and that  
' connectionString connects to master.  
    command.Text = "USE DatabaseName"  
Using connection As New SqlConnection(connectionString)  
    connection.Open()  
    command.ExecuteNonQuery()  
End Using  
// Assumes that command is a SqlCommand object and that  
// connectionString connects to master.  
command.Text = "USE DatabaseName";  
using (SqlConnection connection = new SqlConnection(  
  connectionString))  
  {  
    connection.Open();  
    command.ExecuteNonQuery();  
  }  

Roles de aplicación y agrupación de conexionesApplication Roles and Connection Pooling

Una vez activada una función de aplicación de SQL Server al llamar al procedimiento almacenado de sistema sp_setapprole, no se puede restablecer el contexto de seguridad de la conexión.After a SQL Server application role has been activated by calling the sp_setapprole system stored procedure, the security context of that connection cannot be reset. Sin embargo, cuando se habilita la agrupación, la conexión se devuelve al grupo y se produce un error al utilizar de nuevo la conexión agrupada.However, if pooling is enabled, the connection is returned to the pool, and an error occurs when the pooled connection is reused. Para obtener más información, vea el artículo de Knowledge base "errores de rol de aplicación SQL con agrupación de recursos de OLE DB".For more information, see the Knowledge Base article, "SQL application role errors with OLE DB resource pooling."

Alternativas a los roles de aplicaciónApplication Role Alternatives

Se recomienda aprovechar las ventajas de los mecanismos de seguridad que se pueden usar en lugar de roles de aplicación.We recommend that you take advantage of security mechanisms that you can use instead of application roles. Para obtener más información, vea crear roles de aplicación en SQL Server.For more information, see Creating Application Roles in SQL Server.

Vea tambiénSee also