2012-03-20 5 views
4

Предположим, что мы выполняем множество разных команд sql, а SqlCommand.CommandTimeout - это отпуск со значением по умолчанию 30 секунд..net SqlCommandTimeOut и пул соединений

И давайте просто предположим, что некоторые из этих команд sql - это просто длинный запрос, и мы можем получить исключение тайм-аута.

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

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

UPDATE

Так вот я и спрашиваю о пуле соединений конкретно, это определенно, что код будет закрыть соединение с обработкой исключений, или мы можем только предположить, что используется код, который является образцом предпочтительным названный @dash здесь. Проблема в том, что я вызываю метод Close() или Dispose() в этом объекте SqlConnection, он возвращается в пул соединений, он физически не закрывает его.

Я спрашиваю, когда он будет возвращен в пул, будет ли этот длинный запрос выполняться на стороне SQL Server. И если это возможно, как этого избежать.

UPDATE снова

Спасибо за @dash упоминая, что о транзакции базы данных, да откат будет делать это ждать, и мы не закрываем соединение и вернуть его в бассейн еще. Итак, что, если это просто длинный запрос или обновление, но только одно индивидуальное обновление без какой-либо транзакции базы данных? И особенно я хочу знать, есть ли способ, которым мы можем сказать SQL Server, что мне не нужен результат, пожалуйста, прекратите его запускать?

+1

Отсутствует; нет никакого способа - вы можете Убить запущенный процесс на SQL Server, но вам просто нужно позволить SQL Server управлять тем, что он делает. Как и во всем, если вы решите запустить запрос, который ухудшает производительность сервера, то это ваш выбор :-) – dash

+0

Вы можете убить текущий процесс на SQL Server с помощью команды SQL KILL. KILL SPID и для получения SPID вы можете использовать SELECT @@ SPID или получить все текущие процессы из одной из таблиц sys. –

ответ

5

Все зависит от того, как вы действительно выполняете свои запросы;

Представьте себе следующий запрос:

SqlConnection myConnection = new SqlConnection("connection_string"); 

SqlCommand myCommand = new SqlCommand(); 
myCommand.Connection = myConnection; 
myCommand.CommandType = CommandType.StoredProcedure; 
myCommand.CommandTimeout = some_long_time; 
myCommand.CommandText = "database_killing_procedure_lol"; 

myConnection.Open() //Connection's now open 

myCommand.ExecuteNonQuery(); 

произойдут две вещи; один - этот метод будет стоять в очереди до тех пор, пока не завершится команда. ExecuteNonQuery(). Во-вторых, мы также свяжем соединение из пула соединений в течение всего метода.

Что произойдет, если мы перейдем? Ну, генерируется исключение - исключение SqlException с свойством Number = -2. Однако помните, что в приведенном выше коде отсутствует управление исключениями, поэтому все, что произойдет, это объекты, выходящие из области видимости, и нам нужно будет дождаться их удаления. В частности, наше соединение не будет использоваться повторно, пока это не произойдет.

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

using(SqlConnection myConnection = new SqlConnection("connection_string")) 
{ 
    using(SqlCommand myCommand = new SqlCommand()) 
    { 

     SqlCommand myCommand = new SqlCommand(); 
     myCommand.Connection = myConnection; 
     myCommand.CommandType = CommandType.StoredProcedure; 
     myCommand.CommandTimeout = some_long_time; 
     myCommand.CommandText = "database_killing_procedure_lol"; 

     myConnection.Open() //Connection's now open 

     myCommand.ExecuteNonQuery();  

    } 

} 

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

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

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

EDIT:

Таким образом, вы на самом деле заинтересованы в том, что происходит на стороне сервера SQL ... ответ ... это зависит! CommandTimeout на самом деле является клиентским событием - вы говорите, что если запрос занимает больше, чем n секунд, то я больше не хочу ждать. SQL Server получает сообщение, что это так, но он все еще должен иметь дело с тем, что он сейчас делает, поэтому на самом деле может потребоваться некоторое время, прежде чем SQL Server завершит запрос. Он попытается расставить приоритеты, но об этом.

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

Также очень часто люди сталкиваются с паникой и начинают выдавать команды KILL против идентификатора SQL-процесса, с которым выполняется запрос. Это часто бывает ошибкой, если команда выполняет транзакцию, но часто подходит для длительных отборов.

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

Так что да, сторона ASP.Net будет все в порядке, поскольку ей все равно, но SQL Server по-прежнему должен завершить начатую работу или достичь точки, в которой он может отказаться от этой работы, или откат любых изменений в любых транзакциях, которые были открыты.

Это, очевидно, может повлиять на производительность сервера базы данных в зависимости от запроса!

Даже длинный пробег SELECT или UPDATE или INSERT за пределами транзакции должен быть завершен. SQL Server попытается отказаться от него, как только это возможно, но только если это безопасно. Очевидно, что для UPDATES и INSERT, особенно, он должен достичь точки, в которой база данных по-прежнему непротиворечива. Для SELECT он попытается закончить, как только это будет возможно.

+0

Прошу прощения за то, что я не совсем понимаю, о моем вопросе, я спрашиваю о пуле соединений, но не лучше тренируюсь с ключевым словом «using», пожалуйста, проверьте мой обновленный вопрос. –

+0

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

+0

Эй, я просто обновляю свой вопрос, пожалуйста, проверьте, я действительно задаю другой вопрос, который я закрыл соединение, и он возвращается в пул соединений, будет ли он все еще работать на стороне сервера sql. Я не спрашиваю, как .Net обрабатывает пул соединений. спасибо –

0

Спасибо за @dash упоминая, что о транзакции базы данных, да откат будет делать это ждать, и мы не закрываем соединение и вернуть его в бассейн еще. Итак, что, если это просто длинный запрос select или , но только одно индивидуальное обновление без какой-либо базы данных сделка? И конкретно Я хочу знать, есть ли способ , что мы можем сказать SQL Server, что мне не нужен результат, пожалуйста, остановить его?

Я думаю, что данная ссылка будет отвечать нужно Link1 Link2

+0

Обратите внимание на документацию - «пытается отменить выполнение SqlCommand» - оперативное слово «пытается» - это не гарантировано, я 'Боюсь. – dash