Как решить проблему пула соединений между ASP.NET и SQL Server? - PullRequest
171 голосов
/ 22 марта 2009

Последние несколько дней мы видим это сообщение об ошибке на нашем сайте слишком много:

"Время ожидания истекло. Время ожидания истекший до получения подключение из бассейна. Это может произошло, потому что все объединено соединения использовались и максимальный пул размер достигнут. "

Мы ничего не изменили в нашем коде в течение некоторого времени. Я пересмотрел код, чтобы проверить открытые соединения, которые не закрывались, но нашли все в порядке.

  • Как я могу решить эту проблему?

  • Нужно ли редактировать этот пул?

  • Как мне отредактировать максимальное количество соединений в этом пуле?

  • Какое рекомендуемое значение для сайта с высоким трафиком?


Обновление:

Нужно ли что-то редактировать в IIS?

Обновление:

Я обнаружил, что число активных подключений составляет от 15 до 31, и обнаружил, что максимально допустимое количество подключений, настроенных на сервере SQL, превышает 3200, слишком много - 31, или я должен что-то редактировать в ASP Конфигурация .NET?

Ответы [ 19 ]

184 голосов
/ 22 марта 2009

В большинстве случаев проблемы с пулами соединений связаны с «утечками соединений». Ваше приложение, вероятно, не закрывает свои подключения к базе данных правильно и последовательно. Когда вы оставляете соединения открытыми, они остаются заблокированными, пока сборщик мусора .NET не закроет их для вас, вызвав их метод Finalize().

Вы хотите убедиться, что действительно закрываете соединение . Например, следующий код вызовет утечку соединения, если код между .Open и Close выдает исключение:

var connection = new SqlConnection(connectionString);
connection.Open();
// some code
connection.Close();                

Правильный путь будет следующим:

var connection = new SqlConnection(ConnectionString);
try
{
     connection.Open();
     someCall (connection);
}
finally
{
     connection.Close();                
}

или

using (SqlConnection connection = new SqlConnection(connectionString))
{
     connection.Open();
     someCall(connection);
}

Когда ваша функция возвращает соединение из метода класса , убедитесь, что вы кэшируете его локально и вызываете его метод Close. Вы потеряете соединение, используя этот код, например:

var command = new OleDbCommand(someUpdateQuery, getConnection());
result = command.ExecuteNonQuery();
connection().Close(); 

Соединение, возвращенное после первого вызова getConnection(), не закрывается. Вместо того, чтобы закрывать ваше соединение, эта строка создает новое и пытается закрыть его.

Если вы используете SqlDataReader или OleDbDataReader, закройте их. Несмотря на то, что закрытие самого соединения, кажется, делает свое дело, приложите дополнительные усилия для явного закрытия объектов чтения данных при их использовании.


Эта статья " Почему переполнение пула соединений? " из журнала MSDN / SQL объясняет множество деталей и предлагает некоторые стратегии отладки:

  • Выполнить sp_who или sp_who2. Эти системные хранимые процедуры возвращают информацию из системной таблицы sysprocesses, которая показывает состояние и информацию обо всех рабочих процессах. Как правило, вы увидите один идентификатор процесса сервера (SPID) для каждого соединения. Если вы назвали свое соединение, используя аргумент «Имя приложения» в строке соединения, ваши рабочие соединения будет легко найти.
  • Используйте SQL Server Profiler с шаблоном SQLProfiler TSQL_Replay для отслеживания открытых соединений. Если вы знакомы с Profiler, этот метод проще, чем опрос с использованием sp_who.
  • Используйте системный монитор для мониторинга пулов и соединений. Я обсуждаю этот метод через мгновение.
  • Мониторинг счетчиков производительности в коде. Вы можете отслеживать состояние своего пула соединений и количество установленных соединений, используя процедуры извлечения счетчиков или используя новые элементы управления .NET PerformanceCounter.
28 голосов
/ 01 июня 2016

После установки .NET Framework v4.6.1 из-за этого изменения наши соединения с удаленной базой данных немедленно начали отключаться .

Для исправления просто добавьте параметр TransparentNetworkIPResolution в строку подключения и установите для него значение false :

Сервер = MyServerName; Database = MyDatabase; Trusted_Connection = True; TransparentNetworkIPResolution = False

13 голосов
/ 22 марта 2009

Проверяли ли вы DataReaders, которые не закрыты, и response.redirects перед закрытием соединения или устройства чтения данных. Соединения остаются открытыми, если вы не закрыли их перед перенаправлением.

13 голосов
/ 22 марта 2009

Если ваше использование не увеличилось, кажется маловероятным, что есть просто отставание в работе. ИМО, наиболее вероятным вариантом является то, что что-то использует соединения и не освобождает их быстро. Вы уверены вы используете using во всех случаях? Или (через какой-либо механизм) освободить соединения?

9 голосов
/ 15 июня 2009

Мы также время от времени сталкиваемся с этой проблемой на нашем веб-сайте. Виновником в нашем случае является то, что наша статистика / индексы устарели. Это приводит к тому, что ранее быстро выполняющийся запрос (в конце концов) замедляется и время ожидания истекает.

Попробуйте обновить статистику и / или пересоздать индексы в таблицах, затронутых запросом, и посмотрите, поможет ли это.

5 голосов
/ 22 марта 2009

Я тоже сталкивался с этой проблемой при использовании стороннего уровня данных в одном из моих приложений .NET. Проблема заключалась в том, что слой не закрывал соединения должным образом.

Мы выбросили слой и создали его сами, который всегда закрывает и удаляет связи. С тех пор мы больше не получаем ошибку.

5 голосов
/ 22 марта 2009

Вы можете указать минимальный и максимальный размер пула, указав MinPoolSize=xyz и / или MaxPoolSize=xyz в строке подключения. Однако причиной проблемы может быть другая вещь.

4 голосов
/ 02 января 2018

Вы можете попробовать это тоже для решения проблемы тайм-аута:

Если вы не добавили httpRuntime в свою веб-конфигурацию, добавьте это в <system.web> tag

<sytem.web>
     <httpRuntime maxRequestLength="20000" executionTimeout="999999"/>
</system.web>

и

Измените строку подключения следующим образом;

 <add name="connstring" connectionString="Data Source=DSourceName;Initial Catalog=DBName;Integrated Security=True;Max Pool Size=50000;Pooling=True;" providerName="System.Data.SqlClient" />

При последнем использовании

    try
    {...} 
    catch
    {...} 
    finaly
    {
     connection.close();
    }
3 голосов
/ 31 июля 2013

Это связано главным образом с тем, что соединение не было закрыто в приложении. Используйте «MinPoolSize» и «MaxPoolSize» в строке подключения.

3 голосов
/ 24 августа 2015

В моем случае я не закрывал объект DataReader.

        using (SqlCommand dbCmd = new SqlCommand("*StoredProcedureName*"))
        using (dbCmd.Connection = new SqlConnection(WebConfigurationAccess.ConnectionString))
            {
            dbCmd.CommandType = CommandType.StoredProcedure;

            //Add parametres
            dbCmd.Parameters.Add(new SqlParameter("@ID", SqlDbType.Int)).Value = ID;
.....
.....
            dbCmd.Connection.Open();
            var dr = dbCmd.ExecuteReader(); //created a Data reader here
            dr.Close();    //gotta close the data reader
            //dbCmd.Connection.Close(); //don't need this as 'using' statement should take care of this in its implicit dispose method.
            }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...