【问题标题】:What are the consequences of not closing database connection after an error?出错后不关闭数据库连接会有什么后果?
【发布时间】:2008-09-27 19:04:37
【问题描述】:

我有一个令人头疼的应用程序。它是一个通过 Web 服务连接到 SQL Server 2005 的 .NET 应用程序。该程序的网格由易于超时的长时间运行的存储过程填充。在超时并抛出 SqlException 的情况下,没有执行关闭连接的处理。

这种情况的实际后果是什么?我认为框架或 SQL Server 可能会以一种或另一种方式处理它,但我不确定。

加法 该程序在早上总是运行良好,但使用一个小时左右后它基本上停止工作。问题不在于我不知道如何正确编码连接。我需要知道这些症状是否可能是由未关闭的连接引起的。更改生产代码是一件大事,我想知道这至少有可能成为问题。

结论 我设计这种失败发生在数百个同时连接上。我永远无法在应用程序环境中重现故障情况。将最佳实践答案标记为正确。谢谢大家。

【问题讨论】:

  • 我认为标签应该是 sql-server 而不是问题显示的两个单独的标签
  • 听起来您在生产环境中打开了连接池。启用池化后,即使您告诉它们关闭连接也不会关闭,因此您不关闭它们也没关系。

标签: .net sql sql-server sql-server-2005 web-services


【解决方案1】:

由于 SqlConnection 在处理时关闭,我通常使用这种语法

using (SqlConnection conn = new SqlConnection())
{
  // SqlCode here 
}

【讨论】:

    【解决方案2】:

    有连接限制;如果您的应用程序经常崩溃并且没有自动关闭连接,则新的连接请求将被拒绝。

    也就是说,如果连接没有关闭,连接会在一段时间后超时。

    【讨论】:

      【解决方案3】:

      如果应用程序在一个小时左右后停止工作,那肯定是由于连接未关闭/处置造成的。

      【讨论】:

        【解决方案4】:

        这就是为什么在使用 ADO.Net 时“using”关键字如此重要的原因

         using ( SqlConnection conn = new SqlConnection() )
         {
             ...
         }
        

        这会强制使用 IDispose 接口对 ADO.Net 对象进行一种确定性垃圾回收。

        大多数数据库代码为此使用大量嵌套的“使用”子句。

        【讨论】:

        【解决方案5】:

        如果经常发生这种情况,您可能会用完可用的连接,您应该在执行命令的任何地方使用 finally 来关闭连接。

        【讨论】:

          【解决方案6】:

          垃圾收集器最终会完成你打开的连接对象,但你不知道下次 GC 何时到来。在此之前,如果您有大量流量或者它是共享 sql 服务器,您的池中的连接可能会用完。

          为什么不将它放在 try/catch 块的 finally 部分?

          finally
          {
             if (cn != null)
             {
                cn.Dispose();
                cn = null;
             }
          }
          

          这显然应该在web service方法中完成。

          【讨论】:

          • 你不需要“cn = null;”
          • 我投票支持你是因为你是唯一一个提到池化的人。根据您是否使用连接池,连接的行为有很大不同。
          【解决方案7】:
          try
          {
              sqlCommandObject.Execute(); // this line will throw a timeout exception
          }
          finally
          {
              sqlConnectionObject.Close(); // this will execute no matter what happens
          }
          

          【讨论】:

          • 我认为 MS 和其他人的建议是使用 Dispose() 或正如 Pablo 指出的那样,使用块。 Dispose() 在连接对象上调用 Close(),并在必要时进行其他清理。
          • 这个答案是“正确的”。 msdn.microsoft.com/en-us/library/… "Close 和 Dispose 在功能上是等效的。"
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多