Объединение подключений в пул в SQL Server (ADO.NET)SQL Server Connection Pooling (ADO.NET)

Соединение с сервером базы данных обычно состоит из нескольких длительных шагов.Connecting to a database server typically consists of several time-consuming steps. Необходимо установить физический канал, например сокет или именованный канал, выполнить первоначальное подтверждение установления связи с сервером, выполнить синтаксический анализ данных строки соединения, сервер должен проверить подлинность соединения, а также запустить проверку прикреплений в текущей транзакции и т. д.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.

На практике большинство приложений использует только одно или несколько различных конфигураций соединений.In practice, most applications use only one or a few different configurations for connections. Это означает, что во время выполнения приложения многие идентичные соединения будут повторно открываться и закрываться.This means that during application execution, many identical connections will be repeatedly opened and closed. Чтобы максимально сэкономить расходы на открытие подключений, ADO.NET использует методику оптимизации, называемую созданием пулов соединений.To minimize the cost of opening connections, ADO.NET uses an optimization technique called connection pooling.

Пул соединений снижает количество открытий новых соединений.Connection pooling reduces the number of times that new connections must be opened. Пул хранит владение физическим подключением.The pooler maintains ownership of the physical connection. Он управляет соединениями с помощью поддержания набора активных соединений для каждой конфигурации данного соединения.It manages connections by keeping alive a set of active connections for each given connection configuration. Каждый раз, когда пользователь вызывает метод Open в соединении, организатор пулов ищет в пуле доступное соединение.Whenever a user calls Open on a connection, the pooler looks for an available connection in the pool. Если соединение пула доступно, вместо открытия нового соединения он возвращает его участнику.If a pooled connection is available, it returns it to the caller instead of opening a new connection. При вызове приложением метода Close в соединении вместо закрытия организатор пулов возвращает его в набор активных соединений пула.When the application calls Close on the connection, the pooler returns it to the pooled set of active connections instead of closing it. После возвращения соединения в пул оно готово к повторному использованию при следующем вызове метода Open.Once the connection is returned to the pool, it is ready to be reused on the next Open call.

В пул могут помещаться только соединения с одинаковой конфигурацией.Only connections with the same configuration can be pooled. ADO.NET хранит несколько пулов в одно и то же время, по одному для каждой конфигурации.ADO.NET keeps several pools at the same time, one for each configuration. Соединения разделяются в пулы строкой соединения, а при использовании встроенной безопасности - удостоверением Windows.Connections are separated into pools by connection string, and by Windows identity when integrated security is used. Соединения также заносятся в пул в зависимости от того, прикреплены ли они к транзакции.Connections are also pooled based on whether they are enlisted in a transaction. При использовании метода ChangePassword экземпляр SqlCredential влияет на пул соединений.When using ChangePassword, the SqlCredential instance affects the connection pool. Различные экземпляры SqlCredential используют различные пулы соединений, даже если идентификатор пользователя и пароль совпадают.Different instances of SqlCredential will use different connection pools, even if the user ID and password are the same.

Организация пулов соединений может существенно улучшить производительность и масштабируемость приложения.Pooling connections can significantly enhance the performance and scalability of your application. По умолчанию в ADO.NET включена поддержка пулов соединений.By default, connection pooling is enabled in ADO.NET. Пока организатор пулов не будет явно отключен, он оптимизирует соединения по мере их открытия и закрытия в приложении.Unless you explicitly disable it, the pooler optimizes the connections as they are opened and closed in your application. Также можно указать несколько модификаторов строки соединения для управления поведением пула соединений.You can also supply several connection string modifiers to control connection pooling behavior. Дополнительные сведения см. в подразделе «Управление пулами соединений с помощью ключевых слов строки соединения» далее в этом разделе.For more information, see "Controlling Connection Pooling with Connection String Keywords" later in this topic.

Примечание

Если включено создание пулов соединения и происходит ошибка времени ожидания или другая ошибка входа, то выдается исключение и последующие попытки подключения завершаются ошибкой в течение следующего «интервала блокирования» - 5 секунд.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". Если приложение пытается установить подключение в течение интервала блокирования, то снова выдается первое исключение.If the application attempts to connect within the blocking period, the first exception will be thrown again. Последующие ошибки после завершения интервала блокирования приводят к возникновению новых интервалов блокирования, вдвое превышающих предыдущий период времени блокирования, вплоть до максимального значения в 1 минуту.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.

Создание и назначение пуловPool Creation and Assignment

При первом открытии соединения создается пул соединений, основанный на алгоритме точного совпадения, связанного с пулом строкой соединения.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. Каждый пул соединений связывается с отдельной строкой соединения.Each connection pool is associated with a distinct connection string. При открытии нового соединения, если строка соединения не соответствует в точности существующему пулу, создается новый пул.When a new connection is opened, if the connection string is not an exact match to an existing pool, a new pool is created. Соединения заносятся в пул отдельно для процесса, домена приложения, строки соединения и, если используется встроенная безопасность, для удостоверения Windows.Connections are pooled per process, per application domain, per connection string and when integrated security is used, per Windows identity. Строки соединения должны точно совпадать. Ключевые слова, указанные в различном порядке для одного соединения, будут включены в пул по отдельности.Connection strings must also be an exact match; keywords supplied in a different order for the same connection will be pooled separately.

В следующем примере C# создаются три новых объекта SqlConnection, но для управления ими требуется только два пула соединений.In the following C# example, three new SqlConnection objects are created, but only two connection pools are required to manage them. Обратите внимание, что первая и вторая строки соединения отличаются значениями, присвоенными аргументу 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.  
    }  

Если аргумент MinPoolSize не указан в строке соединения или указано значение 0, соединения в пуле будут закрыты после периода отсутствия активности.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. Однако, если значение аргумента MinPoolSize больше 0, пул соединений не уничтожается, пока не будет выгружен домен приложения AppDomain и не завершится процесс.However, if the specified MinPoolSize is greater than zero, the connection pool is not destroyed until the AppDomain is unloaded and the process ends. Обслуживание неактивных или пустых пулов требует минимальных системных издержек.Maintenance of inactive or empty pools involves minimal system overhead.

Примечание

Пул автоматически очищается при возникновении неустранимой ошибки, например переходе на другой ресурс.The pool is automatically cleared when a fatal error occurs, such as a failover.

Добавление соединенийAdding Connections

Пул соединений создается для каждой уникальной строки соединения.A connection pool is created for each unique connection string. При создании пула создается множество объектов соединения, которые добавляются в пул для удовлетворения требования к минимальному размеру пула.When a pool is created, multiple connection objects are created and added to the pool so that the minimum pool size requirement is satisfied. Соединения добавляются в пул по необходимости, вплоть до указанного максимального размера пула (по умолчанию - 100).Connections are added to the pool as needed, up to the maximum pool size specified (100 is the default). Соединения освобождаются обратно в пул при закрытии или ликвидации.Connections are released back into the pool when they are closed or disposed.

При запросе объекта SqlConnection он получается из пула при наличии готового к использованию соединения.When a SqlConnection object is requested, it is obtained from the pool if a usable connection is available. Чтобы соединение можно было использовать, оно не должно использоваться, иметь совпадающий контекст транзакции либо не иметь связи с каким-либо контекстом транзакций и иметь допустимую ссылку на сервер.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.

Организатор пулов соединений обрабатывает запросы соединений путем их повторного размещения после возврата в пул.The connection pooler satisfies requests for connections by reallocating connections as they are released back into the pool. Если достигнут максимальный размер пула, а пригодные соединения недоступны, запрос помещается в очередь.If the maximum pool size has been reached and no usable connection is available, the request is queued. Затем организатор пулов пытается вернуть любое соединение до истечения времени ожидания (по умолчанию - 15 секунд).The pooler then tries to reclaim any connections until the time-out is reached (the default is 15 seconds). Если организатор пулов не может обработать запрос до истечения времени ожидания соединения, возникнет исключение.If the pooler cannot satisfy the request before the connection times out, an exception is thrown.

Внимание!

Настоятельно рекомендуется всегда закрывать соединение после его использования, чтобы оно вернулось в пул.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. Это Close можно сделать с помощью методов Connection или объекта Dispose или путем открытия всех C# Using соединений внутри using инструкции в или инструкции в 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. Соединения, которые явно не закрыты, нельзя добавить или вернуть в пул.Connections that are not explicitly closed might not be added or returned to the pool. Дополнительные сведения см. в разделе оператор using или инструкции. Удаление системного ресурса для Visual Basic.For more information, see using Statement or How to: Dispose of a System Resource for Visual Basic.

Примечание

В методе Close вашего класса нельзя вызывать методы Dispose или Connection объектов DataReader, Finalize или любого другого управляемого объекта.Do not call Close or Dispose on a Connection, a DataReader, or any other managed object in the Finalize method of your class. В методе завершения следует освобождать только неуправляемые ресурсы, которыми ваш класс непосредственно владеет.In a finalizer, only release unmanaged resources that your class owns directly. Если класс не владеет какими-либо неуправляемыми ресурсами, не включайте в его определение метод Finalize.If your class does not own any unmanaged resources, do not include a Finalize method in your class definition. Дополнительные сведения см. в разделе Сборка мусора.For more information, see Garbage Collection.

Дополнительные сведения о событиях, связанных с открытием и закрытием соединений, см. в разделе Аудит входа в класс событий и аудит Logout в 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.

Удаление соединенийRemoving Connections

Организатор пулов соединений удаляет соединение из пула после его простоя в течение примерно 4-8 минут или при определении им разрыва соединения с сервером.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. Обратите внимание, что разорванное соединение можно определить только после попытки связи с сервером.Note that a severed connection can be detected only after attempting to communicate with the server. При обнаружении соединения, которое больше не имеет связи с сервером, оно помечается как недействительное.If a connection is found that is no longer connected to the server, it is marked as invalid. Недействительные соединения удаляются из пула соединений только после их закрытия или возврата.Invalid connections are removed from the connection pool only when they are closed or reclaimed.

Если существующее соединение с сервером исчезло, оно может быть удалено из пула, даже если организатор пулов соединений не определил разорванное соединение и не пометил его как недопустимое.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. Это происходит вследствие того, что проверка соединения на допустимость уничтожит преимущества существования организатора пулов, став причиной вызова очередного цикла приема-передачи с сервером.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. В этом случае первая попытка использовать соединение определит его разрыв и вызовет исключение.When this occurs, the first attempt to use the connection will detect that the connection has been severed, and an exception is thrown.

Очистка пулаClearing the Pool

В ADO.NET 2,0 появились два новых метода очистки пула: ClearAllPools и. ClearPoolADO.NET 2.0 introduced two new methods to clear the pool: ClearAllPools and ClearPool. Метод ClearAllPools очищает пулы соединений данного поставщика, а метод ClearPool - пул, связанный с конкретным соединением.ClearAllPools clears the connection pools for a given provider, and ClearPool clears the connection pool that is associated with a specific connection. Если во время вызова методов соединения использовались, они соответствующим образом помечаются.If there are connections being used at the time of the call, they are marked appropriately. При их закрытии вместо возвращения в пул они удаляются.When they are closed, they are discarded instead of being returned to the pool.

Поддержка транзакцийTransaction Support

Соединения выбираются из пула и назначаются в зависимости от контекста транзакции.Connections are drawn from the pool and assigned based on transaction context. Если в строке соединения не указан аргумент Enlist=false, пул соединений гарантирует прикрепление соединения к контексту Current.Unless Enlist=false is specified in the connection string, the connection pool makes sure that the connection is enlisted in the Current context. После закрытия и возврата соединения в пул с прикрепленной транзакцией System.Transactions оно резервируется таким образом, что следующий запрос к пулу соединений с той же транзакцией System.Transactions вернет это соединение, если оно доступно.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. Если при выдаче такого запроса в пуле нет доступных соединений, соединение берется и прикрепляется из части пула, не использующей транзакции.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. Если доступных соединений нет во всех частях пула, создается и прикрепляется новое соединение.If no connections are available in either area of the pool, a new connection is created and enlisted.

При закрытии соединения оно освобождается обратно в пул и в соответствующий подраздел в зависимости от его контекста транзакции.When a connection is closed, it is released back into the pool and into the appropriate subdivision based on its transaction context. Поэтому можно закрыть соединение без создания ошибки, даже если распределенная транзакция все еще находится в ожидании.Therefore, you can close the connection without generating an error, even though a distributed transaction is still pending. Это позволит зафиксировать или отменить распределенную транзакцию позже.This allows you to commit or abort the distributed transaction later.

Управление пулами соединений с помощью ключевых слов строки соединенияControlling Connection Pooling with Connection String Keywords

Свойство ConnectionString объекта SqlConnection поддерживает пары «ключ-значение» из строки соединения, с помощью которых можно изменять логику организации пулов соединений.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. Дополнительные сведения см. в разделе ConnectionString.For more information, see ConnectionString.

Фрагментация пулаPool Fragmentation

Фрагментация пула является распространенной проблемой для многих веб-приложений, в которых может создаваться большое количество пулов, которые не освобождаются, пока существует процесс.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. Это оставляет большое количество соединений открытыми и потребляющими память, что приводит к ухудшению производительности.This leaves a large number of connections open and consuming memory, which results in poor performance.

Фрагментация пула из-за встроенной безопасностиPool Fragmentation Due to Integrated Security

Соединения заносятся в пул в соответствии со строкой соединения, а также удостоверением пользователя.Connections are pooled according to the connection string plus the user identity. Таким образом, при использовании на веб-узле обычной проверки подлинности или проверки подлинности Windows, а также встроенной безопасности имени входа получается один пул на пользователя.Therefore, if you use Basic authentication or Windows Authentication on the Web site and an integrated security login, you get one pool per user. Несмотря на то, что это улучшает производительность последующих запросов пользователя к базе данных, для него недоступны преимущества соединений, установленных другими пользователями.Although this improves the performance of subsequent database requests for a single user, that user cannot take advantage of connections made by other users. Это также приводит по крайней мере к одному соединению с сервером базы данных для каждого пользователя.It also results in at least one connection per user to the database server. Это является побочным эффектом данной архитектуры веб-приложений, который разработчики должны соизмерить с требованиями безопасности и аудита.This is a side effect of a particular Web application architecture that developers must weigh against security and auditing requirements.

Фрагментация пула из-за многочисленных баз данныхPool Fragmentation Due to Many Databases

Многие поставщики услуг Интернет размещают несколько веб-узлов на одиночном сервере.Many Internet service providers host several Web sites on a single server. Они могут использовать одну базу данных для подтверждения проверки подлинности имени входа с помощью форм и затем открывать соединение с определенной базой данных для этого пользователя или группы пользователей.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. Соединение с базой данных проверки подлинности заносится в пул и используется всеми.The connection to the authentication database is pooled and used by everyone. Однако для каждой базы данных существует отдельный пул соединений, увеличивающий количество соединений с сервером.However, there is a separate pool of connections to each database, which increase the number of connections to the server.

Это также является побочным эффектом конструкции приложений.This is also a side-effect of the application design. При соединении с SQL Server существует относительно простой способ устранения этого побочного эффекта без нарушения безопасности.There is a relatively simple way to avoid this side effect without compromising security when you connect to SQL Server. Вместо соединения каждого пользователя или группы с отдельной базой данных устанавливается соединение с одной базой данных на сервере, а затем выполняется инструкция Transact-SQL USE, чтобы переключиться на требуемую базу данных.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. Следующий фрагмент кода демонстрирует создание первоначального соединения с базой данных master и последующее переключение на требуемую базу данных, указанную в строковой переменной 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();  
  }  

Роли приложений и пул соединенийApplication Roles and Connection Pooling

После активации роли приложения SQL Server с помощью вызова системной хранимой процедуры sp_setapprole контекст безопасности данного соединения сбросить нельзя.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. Однако, если использование пула включено, соединение возвращается в пул и при повторном использовании соединения возникает ошибка.However, if pooling is enabled, the connection is returned to the pool, and an error occurs when the pooled connection is reused. Дополнительные сведения см. в статье базы знаний "ошибки роли приложения SQL с OLE DB пула ресурсов".For more information, see the Knowledge Base article, "SQL application role errors with OLE DB resource pooling."

Альтернативы ролям приложенийApplication Role Alternatives

Рекомендуется пользоваться преимуществом новых механизмов безопасности, которые пришли на смену ролям приложения.We recommend that you take advantage of security mechanisms that you can use instead of application roles. Дополнительные сведения см. в разделе Создание ролей приложения в SQL Server.For more information, see Creating Application Roles in SQL Server.

См. такжеSee also