Пул соединений SQL Server не обнаруживает закрытые соединения?

в течение многих лет я испытывал очень странные проблемы во всех моих веб-приложениях, которые подключаются к SQL server.

проблема в том, что если что-то происходит с сервером базы данных (перезапуск сервера или другая проблема), de web app перестает работать с этого момента, даже если сервер базы данных жив и здоров после этого.

что происходит, что каждый ADO.NET операция (ExecuteNonQuery, CreateReader, BeginTransaction, ...) не с InvalidOperationException:"недопустимая операция. Соединение закрыто". Кажется, что призыв к SqlConnection.Open () получает соединение из пула приложений, который... закрыто!

согласно документации, пул соединений должен автоматически удалять разорванные соединения из пула соединений, но, по-видимому, закрытое соединение не считается "разорванным", поэтому вызов SqlConnection.Open () счастливо возвращает закрытое соединение, предполагая, что оно открыто, не проверяя это.

мое текущее решение, чтобы проверить состояние соединения сразу после его открытия:

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

   if (connection.State != ConnectionState.Open)
   {
      SqlConnection.ClearAllPools();

      connection.Open();
   }

   // ...
}

Это решение, кажется, работает сейчас, но я не чувствую себя комфортно делать это.

Итак, мои вопросы:

  1. почему SqlConnection.Open () возврат закрытых соединений из пула соединений?
  2. это мой обходной путь действительны?
  3. есть ли лучший способ справиться с этим?

2 ответов


некоторое время назад я провел аналогичное исследование объединения соединений по несколько иной причине, но, надеюсь, будет полезно. Вот что я нашел:--1-->

  1. даже когда вы закрываете соединение в коде, оно возвращается в пул без фактического закрытия соединения-готов к дальнейшему использованию.
  2. если это соединение разрывается (т. е. перезапуск SQL Server), когда соединение возвращается из пула для другого вызывающего абонента, и этот вызывающий абонент делает .Открой на него, он не ошибка в тот момент, когда сервер базы данных все еще не работает. Это часть преимущества производительности пула соединений, поскольку он фактически не возвращается на сервер базы данных для подключения.
  3. когда вы фактически пытаетесь выполнить команду против соединения (например, ExecuteNonQuery), именно в этот момент он фактически выдает исключение

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

Это были некоторые статьи, которые я посмотрел в то время:
Sql Server Google Group
использование пула соединений в ASP.NET

Edit:
Это звучит странно, что плохое соединение остается в бассейне навсегда - ты конечно, это определенно так, и это не просто несколько плохих соединений? Если вы уверены, то похоже, что эти соединения не освобождаются должным образом в вашем коде. этой еще одна очень хорошая статья, я читал некоторое время назад, что говорит (цитата):

Автоматическая Промывка Соединений

Если объединенное соединение остается в "закрытое, но многоразовое" состояние для от 4 до 8 минут (интервал выбран наугад) соединение механизм объединения закрывает физический соединение и сбрасывает пул соединение. То есть, если число остальных соединений больше чем минимальные соединения настроено для пула (по умолчанию is 0). Отметим, что соединения должны были закрыты приложением (и выпущенный назад к бассейну) перед это может быть предметом автоматического освобождать. Если вы не закроете соединение в коде или сироте Объект соединения, объединение механизм будет делать ничего. Нет, аргументы ConnectionString отсутствуют измените значение тайм-аута.


мы видели ту же проблему с C++, используя ADO. Несколько лет назад, после работы с поддержкой Microsoft, мы также реализовали аналогичную логику повтора в коде и сбросили пул соединений, который решил проблему.

Если есть лучший обходной путь, люди в Microsoft Support либо не знали об этом, либо не делились (в то время в любом случае).