web-dev-qa-db-fra.com

Que se passe-t-il lorsque vous oubliez de fermer et de désallouer le curseur?

Laisser le curseur ouvert est connu comme une mauvaise pratique. Mais que se passe-t-il vraiment lorsque vous oubliez de le fermer et/ou de le désallouer? Comment cela affecte-t-il SQL Server, la connexion/session? Existe-t-il des différences de conséquences pour les requêtes, les procédures stockées et les déclencheurs utilisant des curseurs?

32
Mike

Cela dépend si vous avez déclaré le curseur localement ou globalement (et quelle est la valeur par défaut dans votre environnement - la valeur par défaut est globale mais vous pouvez le changer).

Si le curseur est global, il peut rester "vivant" dans SQL Server jusqu'à ce que le dernier morceau de code soit touché dans la portée dans laquelle il a été créé. Par exemple, si vous appelez une procédure stockée qui crée un curseur global, puis appelez 20 autres procédures stockées, le curseur restera actif pendant l'exécution de ces 20 autres procédures stockées, jusqu'à ce que l'appelant sorte du champ d'application. Je crois que cela restera vivant au niveau de la session, pas au niveau de la connexion, mais je n'ai pas testé cela à fond. Si le curseur est déclaré local, il ne doit rester que dans la portée de l'objet actuel (mais encore une fois, c'est théorique, et je n'ai pas fait de tests de mémoire de bas niveau approfondis pour le confirmer).

Le concept général, cependant, devrait être: lorsque vous avez terminé avec quelque chose, dites-le.

Afin de rendre mes curseurs aussi efficaces que possible, j'utilise toujours les déclarations suivantes:

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

J'ai également entendu dire qu'il peut y avoir des problèmes de mémoire si vous ne faites que CLOSE ou seulement DEALLOCATE donc je fais toujours les deux quand j'ai fini:

CLOSE c;
DEALLOCATE c;

Cependant, combien de curseurs avez-vous lorsque le nettoyage de cette syntaxe pose problème? Si vous avez des centaines de curseurs dans votre système, c'est certainement un drapeau rouge pour moi.

MODIFIER

En guise d'addendum, je tiens simplement à préciser que les curseurs en eux-mêmes ne sont pas mauvais. Ils sont souvent mal utilisés et abusés, bien que - mis en œuvre dans les cas où une solution plus efficace basée sur un ensemble aurait pu avoir été mise en œuvre, mais la personne chargée d'écrire la requête ne pouvait que penser de manière procédurale. Quelques cas où les curseurs ont du sens:

  • Totaux cumulés. Lors de mes tests, les curseurs effacent toutes les solutions basées sur des ensembles pré-SQL 2012 (au moins celles qui sont documentées et prises en charge0.
  • Diverses tâches administratives, par exemple appeler une procédure stockée pour chaque ligne d'une table ou pour chaque table ou base de données.
  • Lorsque l'alternative basée sur un ensemble est extraordinairement complexe ou que la tâche est ponctuelle.
30
Aaron Bertrand

Ne pas fermer un curseur gardera les verrous actifs qu'il détient sur les lignes où il est positionné. Même après la fermeture, une référence est conservée dans les structures de données que le curseur utilise (afin qu'il puisse être rouvert) Ces structures sont spécifiques au serveur SQL (il ne s'agit donc pas uniquement d'espace mémoire ou de poignées) et dépendent de ce que le curseur est réellement faire, mais ils seront généralement des tables temporaires ou des ensembles de résultats de requête.

Ne pas désaffecter AFAIK ne concerne que les performances. Les ressources susmentionnées resteront allouées et auront donc un effet négatif sur les performances du serveur.

les ressources allouées par les curseurs (ouverts ou fermés, mais non désalloués) resteront allouées jusqu'à la fermeture de la session (ou de la connexion)

6
Dirk

"Une variable de curseur ne doit pas être explicitement désallouée. La variable est implicitement désallouée lorsqu'elle sort du champ d'application. "

Référence: http://msdn.Microsoft.com/en-us/library/ms188782.aspx

6
Eclipses