Пул соединений SQL Server не обнаруживает закрытые соединения? - PullRequest
18 голосов
/ 28 января 2010

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

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

В результате происходит сбой каждой операции 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 ]

12 голосов
/ 28 января 2010

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

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

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

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

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

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

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

2 голосов
/ 28 января 2010

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

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

...