Будут ли объединенные в пул SQL-соединения очищаться, если на них все еще есть ссылка?

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

Я поддерживаю, на основе документации , что если физическое соединение какое-то время бездействует, оно будет восстановлено через некоторое время, даже если ссылка на объект SQLConnection остается удерживаемой.

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

Я признаю, что документация расплывчата в вопросе удерживаемых ссылок.

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

Так какой же это?

РЕДАКТИРОВАТЬ:

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

Открытые соединения все еще могут быть прерваны, но неясно, помечает ли пулер это как недействительное, если оно все еще удерживается клиентским приложением как открытое (т.е. клиентское приложение еще не вызвало закрытие прерванного соединения). Не уверен, что это действительно имеет значение, кроме как часть подсчета пула.


person Erik Funkenbusch    schedule 30.09.2012    source источник
comment
Итак, тайм-аут соединения по умолчанию составляет 30 секунд — превышение этого тайм-аута приведет к закрытию соединения с исключением и возврату пулом. Однако, если время ожидания не ограничено, открытое соединение не будет восстановлено.   -  person Oded    schedule 30.09.2012
comment
@Oded - я думал, что тайм-аут был только на то, как долго фреймворк будет пытаться подключиться. Тем не менее, если это правда, это на самом деле не решает вопрос.   -  person Erik Funkenbusch    schedule 30.09.2012
comment
Я, наверное, думаю о времени жизни соединения...   -  person Oded    schedule 30.09.2012
comment
Как вы думаете, в какой части документов говорится, что незанятое соединение может быть восстановлено?   -  person Henk Holterman    schedule 30.09.2012
comment
@HenkHolterman - раздел об удалении соединений.   -  person Erik Funkenbusch    schedule 01.10.2012


Ответы (3)


Я могу сказать вам со 100% уверенностью, что соединение НЕ возвращается в пул, пока не будет освобождено. У меня был сеанс создания временной таблицы, и я оставил ее висящей в ожидании ввода пользователя. Пользователь возвращается через 6 минут, нажимает кнопку и продолжает с тем же SPID, и жизнь во временной таблице продолжается.

Применяя логику, это имеет смысл, потому что можете ли вы представить хаос, если вы потеряете SPID только потому, что вы бездействовали в течение X минут? Должны ли вы продолжать «пинговать» SQL Server с помощью команды только для того, чтобы поддерживать его в рабочем состоянии? (это было бы безумием)


Похоже, вы путаете два понятия. Когда соединение закрывается, оно возвращается в пул. Если он выходит за рамки, он неявно закрывается -> возвращается в пул. Ссылка на "бездействие" относится к тому моменту, когда соединение в пуле становится бездействующим, а не когда на него активно ссылаются и не закрывается. Удержанное соединение даже не находится в пуле, чтобы иметь право на какой-либо тип очистки. Освобождение ресурсов из пула имеет смысл, потому что веб-приложение может легко увеличить количество подключений до сотен, а затем в течение следующих нескольких месяцев оставаться на уровне около 20 или около того активных одновременных подключений.

person RichardTheKiwi    schedule 30.09.2012
comment
Я думаю, что путаница здесь связана с терминологией Closed. Похоже, дело в том, что документация относится к закрытию физического соединения как к удалению соединения из пула. В то время как закрытие относится к выпуску открытого физического соединения обратно в пул для повторного использования. - person Erik Funkenbusch; 01.10.2012

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

«Удерживаемая ссылка» здесь несущественна, точка «открыта». Чтобы правильно переработать соединение, вам нужно Dispose() или Close() его.

person Henk Holterman    schedule 30.09.2012
comment
Вы не совсем улавливаете тонкость вопроса. Вопрос в отношении системы очистки пула соединений. - person Erik Funkenbusch; 01.10.2012
comment
И что/где эта система очистки? Страница, на которую вы ссылаетесь, не упоминает об этом. - person Henk Holterman; 01.10.2012
comment
Средство пула соединений периодически сканирует пулы соединений в поисках неиспользуемых соединений, которые не были закрыты с помощью Close или Dispose, и восстанавливает те, которые он находит. - person Erik Funkenbusch; 01.10.2012
comment
Да, ты прав. Но «неиспользованный» определен не очень хорошо. Лучше процитируйте эту часть в верхней части вопроса. - person Henk Holterman; 01.10.2012

Я только что запустил следующую программу:

        var conn = new SqlConnection("...");
        conn.Open();
        conn.ExecuteNonQuery("select null");
        Thread.Sleep(TimeSpan.FromMinutes(11));
        conn.ExecuteNonQuery("select null");

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

Это, конечно, ничего не доказывает (только если оно не работало правильно). Reflector показывает, что пул очищается в первый раз через 6,5 минут, а затем каждые 30 секунд:

private Timer CreatePruningTimer()
{
    return new Timer(new TimerCallback(this.PruneConnectionPoolGroups), null, 240000, 30000);
}

Таким образом, тест должен был выявить проблему.

Теперь предложение в документах не особенно ясно. В нем не упоминается GC или даже ссылки на объекты (в вашем вопросе вы говорите, что это так, но это не так).

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

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

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

  1. Это приведет к случайным сбоям, которые невозможно предотвратить (только повторной попыткой).
  2. Это прервало бы транзакции, которые просто прекрасны
  3. Это сделало бы длительные транзакции невозможными.
  4. Я не вижу причины, почему такое поведение должно иметь место
  5. Предложение в документах можно интерпретировать следующим образом: пул периодически возвращает соединения, которые не были закрыты, но соответствующий объект SqlConnection был подвергнут сборке мусора (обнаружение этого с помощью WeakReference или чего-то подобного). Я предполагаю, что автор документа Microsoft имел в виду это или не понял проблему (правдоподобно!)
  6. Тест не выявил проблему
  7. Как SSMS удается выполнять часовые запросы? На SSMS должно распространяться такое же ограничение.
person usr    schedule 30.09.2012
comment
Сборщик мусора вызывает finalize, который закрывает соединение. Так что № 5 не имеет большого значения. Часовые запросы не простаивают. - person Erik Funkenbusch; 01.10.2012
comment
Эта фраза была плохо сформулирована. Я почистил его. - person usr; 01.10.2012