忘记关闭和取消分配光标会发生什么?

时间:2012-03-07 16:46:00

标签: sql-server tsql cursor

将光标打开被称为不良做法。但是当你忘记关闭和/或解除分配时会发生什么?它如何影响SQL Server,连接/会话? 使用游标的查询,存储过程和触发器的后果是否有任何差异?

3 个答案:

答案 0 :(得分:29)

这取决于您是在本地还是全局声明游标(以及您的环境中的默认值 - 默认为全局,但您可以更改它)。

如果光标是全局的,那么它可以保持" alive"在SQL Server中,直到在创建它的范围内触及最后一段代码。例如,如果您调用创建全局游标的存储过程,然后调用其他20个存储过程,则当其他20个存储过程正在运行时,游标将继续运行,直到调用者超出范围。我相信它会在会话级别保持活跃,而不是连接级别,但还没有彻底测试过。如果光标被声明为local,那么它应该只保留在当前对象的范围内(但同样,这是理论上的,我还没有做过广泛的低级内存测试来确认)。

但是,一般的概念应该是:当你完成某事时,就这样说。

为了使我的游标尽可能高效,我总是使用以下声明:

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

我也听说如果你只CLOSEDEALLOCATE,可能会出现内存问题,所以在我完成这项工作时我总是这样做:

CLOSE c;
DEALLOCATE c;

但是,你有多少游标可以清除这种语法?如果你的系统中有数百个游标,那对我来说无疑是一个红旗。

编辑

作为附录,我只想澄清游标本身并不坏。但是,它们经常被误用和滥用 - 在实现更高效,基于集合的解决方案 的情况下实现,但负责编写查询的人只能在程序上进行思考。游标有意义的几个案例:

  • 运行总计。在我的测试中,游标会删除所有基于SQL 2012之前的基于集合的解决方案(至少是那些记录和支持的解决方案。
  • 各种管理任务,例如为表中的每一行或每个表或数据库调用存储过程。
  • 当基于集合的替代方案非常复杂,或者任务是一次性的时候。

答案 1 :(得分:6)

不关闭游标会使锁保持活动状态,使其保持在它所在的行上。 即使关闭后,参考仍保留在光标正在使用的数据结构中(因此可以重新打开) 这些结构是特定于SQL服务器的(因此它不仅仅是内存空间或句柄等)并且取决于游标实际执行的操作,但它们通常是临时表或查询结果集。

不解除分配AFAIK只与性能有关。上述资源将保持分配状态,从而对服务器性能产生负面影响。

从(打开或关闭但未解除分配的)游标分配的资源将保持分配,直到会话(或连接)关闭为止

答案 2 :(得分:6)

“不必显式释放游标变量。当变量超出范围时,隐式释放变量。“

参考:http://msdn.microsoft.com/en-us/library/ms188782.aspx