Подтвердить что ты не робот

Что происходит, когда вы забудете закрыть и освободить курсор?

Отказ от открытия курсора известен как плохая практика. Но что на самом деле происходит, когда вы забываете закрыть и/или освободить его? Как это влияет на SQL Server, соединение/сеанс? Существуют ли какие-либо различия в последствиях для запросов, хранимых процедур и триггеров с использованием курсоров?

4b9b3361

Ответ 1

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

Если курсор является глобальным, он может оставаться "живым" в SQL Server до тех пор, пока последний фрагмент кода не коснется области, в которой он был создан. Например, если вы вызываете хранимую процедуру, которая создает глобальный курсор, тогда вызовите 20 других хранимых процедур, курсор будет работать, пока остальные 20 хранимых процедур будут запущены, пока вызывающий абонент не выйдет из области видимости. Я считаю, что он останется в живых на уровне сессии, а не на уровне соединения, но не проверил это полностью. Если курсор объявлен как локальный, то он должен оставаться только в области для текущего объекта (но опять же, это теоретически, и я не проводил обширные тесты уровня низкого уровня для подтверждения).

Общая концепция, однако, должна быть: когда вы закончите что-то, скажите так.

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

DECLARE c CURSOR
  LOCAL STATIC FORWARD_ONLY READ_ONLY
  FOR SELECT ...

Я также слышал, что могут быть проблемы с памятью, если вы только CLOSE или только DEALLOCATE, поэтому я всегда выполняю оба действия:

CLOSE c;
DEALLOCATE c;

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

EDIT

В качестве дополнения я просто хочу уточнить, что курсоры сами по себе не так уж плохи. Однако их часто злоупотребляют и злоупотребляют, но реализованы в тех случаях, когда более эффективное решение на основе набора может быть реализовано, но лицо, которому поручено писать запрос, может думать только процедурно. Несколько случаев, когда курсоры имеют смысл:

  • Текущие итоги. В моем тестировании курсоры уничтожают все предустановленные SQL-запросы на основе до 2012 года (по крайней мере те, которые документированы и поддерживаются0.
  • Различные административные задачи, например. вызывать хранимую процедуру для каждой строки в таблице или для каждой таблицы или базы данных.
  • Если альтернатива, основанная на наборе, чрезвычайно сложна, или задача является одноразовой.

Ответ 2

"Переменная курсора не должна быть явно освобождена. Переменная неявно освобождается, когда она выходит из области видимости".

Ссылка: http://msdn.microsoft.com/en-us/library/ms188782.aspx

Ответ 3

Не закрывая курсор, он будет удерживать блокировки активными, которые он удерживает в строках, где он расположен. Даже после закрытия ссылки сохраняются в структурах данных, которые использует курсор (так что их можно снова открыть) Эти структуры специфичны для SQL-сервера (поэтому это не просто пространство памяти или дескрипторы или так) и зависят от того, что на самом деле делает курсор, но обычно это временные таблицы или наборы результатов запроса.

Не освобождать AFAIK только от производительности. Вышеупомянутые ресурсы останутся распределенными и, таким образом, окажут отрицательное влияние на производительность сервера.

выделенные ресурсы из (открытых или закрытых, но не освобожденных) курсоров будут оставаться выделенными до закрытия сеанса (или соединения)