Sql server 当您忘记关闭和释放游标时会发生什么?

Sql server 当您忘记关闭和释放游标时会发生什么?,sql-server,tsql,cursor,Sql Server,Tsql,Cursor,将光标保持打开状态被认为是一种糟糕的做法。但当你忘记关闭和/或取消分配时,会发生什么呢?它如何影响SQL Server、连接/会话? 使用游标的查询、存储过程和触发器的结果是否存在差异?这取决于您是本地声明游标还是全局声明游标(以及您的环境中的默认值是什么-默认值是全局的,但您可以更改它) 如果光标是全局的,那么它可以在SQL Server中保持“活动”,直到最后一段代码在创建它的作用域中被触及。例如,如果调用一个创建全局游标的存储过程,然后调用20个其他存储过程,则当其他20个存储过程运行时,

将光标保持打开状态被认为是一种糟糕的做法。但当你忘记关闭和/或取消分配时,会发生什么呢?它如何影响SQL Server、连接/会话?
使用游标的查询、存储过程和触发器的结果是否存在差异?

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

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

不过,一般的概念应该是:当你完成某件事时,说出来

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

DECLARE c CURSOR
  LOCAL STATIC FORWARD_ONLY READ_ONLY
  FOR SELECT ...
我还听说,如果仅
关闭
或仅
解除分配
可能会出现内存问题,因此我总是在完成后同时执行这两项操作:

CLOSE c;
DEALLOCATE c;
但是,在清理此语法是一个问题的地方,您有多少游标?如果你的系统中有数百个游标,那对我来说肯定是个危险信号

编辑

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

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

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

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


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

“游标变量不必显式解除分配。变量超出范围时将隐式解除分配。”


参考文献:

在我使用的数据库中声明的本地光标的触发器很少,那些没有被关闭,没有被释放。这是一个bug还是本地游标的正确使用?不明白你认为哪个部分可能是一个bug。我建议,所有这些光标都可以被一个更高效的集合所取代。-基于游标的解决方案,根本不涉及游标。但我不知道触发器的作用。游标用于在插入和删除的表中的每一行上调用某些存储过程,可能与其他表连接。您仍然认为双关闭模式是必要的吗?因为这个答案是popular清理这一部分可能是值得的。代码质量问题,执行行为没有区别。我还可以提出这样的论点,即在出现错误的情况下,这些语句都不会运行。因此无论如何,它们都不能完全依赖。您能否澄清不释放游标将保留资源多长时间?以及系统将保留哪些类型的资源ry/handles/etc?用一些额外的信息更新了答案谢谢,德克。正如Aaron在他的答案中注意到的,游标的释放行为取决于游标是本地的还是全局的。正如在本地游标中所说的,当超出范围时,将自动释放。我感兴趣的是,未释放的游标将泄漏哪些资源除了表锁。取消分配游标变量与取消分配游标不同。在同一页中:“取消分配@cursor\u variable\u name语句只删除命名变量对游标的引用。”是的,您是对的,但是正如官方文档中所写的,您不需要取消分配变量,因此可以避免使用额外的代码。