【问题标题】:ASP.net Timeouts due to connections not being closed由于连接未关闭而导致 ASP.net 超时
【发布时间】:2011-06-15 11:53:07
【问题描述】:

超时。在从池中获取连接之前超时时间已过。这可能是因为所有池连接都在使用中并且已达到最大池大小。

这是我很久以前开发的第一个 ASP.net 网站,它在很多页面的顶部(和很多方法)都有这段代码。

cn = new SqlConnection(ConfigurationManager.ConnectionStrings["LocalSqlServer"].ToString());
cn.Open();

很多页面没有:

cn.Close();

也没有一个页面做using(SqlConnection...),(尽管所有的数据阅读器都在使用块)。

第一个问题是,错误的主要候选者是?

第二个问题是,解决此重构/手动搜索未关闭连接的最佳方法是什么?我知道这是一个丑陋的 hack,但是重构所花费的时间会很长,但是我们可以设置一个计划任务,每天凌晨 3 点回收一次连接池吗?

【问题讨论】:

    标签: c# asp.net iis-7 database-connection connection-pooling


    【解决方案1】:

    是的,这是错误的主要原因。目前,其中许多连接将等到下一次 GC 重新池化底层连接。您将很快耗尽池(和数据库连接)。

    重构它的最好方法是添加缺少的using,这样连接就被限定了。就个人而言,我也会将其重构为单一方法,即

    using(var cn = SomeUtilityClass.GetOpenConnection())
    {...}
    

    除非将阅读器标记为close the connection,否则关闭阅读器作用不大;并让数据阅读器关闭连接(通过行为)某种是可行的,但它假设您已经尽可能地使用阅读器 - 它在错误情况下不一定表现良好。 p>

    【讨论】:

    • 谢谢 Marc,这个设计特别糟糕,因为连接变量被传递给其他方法,这很重要吗?
    • @Tom 只要他们使用连接并完成它,根本不会。显然,您的 using 块需要封装这些方法。
    【解决方案2】:

    即使我在曾经使用过的应用程序中也遇到过这个错误。我发现的问题是相同的——没有使用语句,也没有关闭电话。

    我建议您在整个项目中搜索 SqlConnection,然后在 using 语句中包含 SqlConnection、SqlCommand 和 SqlDataAdapter,并在 sqlconnection using 语句中执行 connection.close。在配置文件中与此一起增加连接字符串中连接的超时。您也可以使用 SqlCommand 的 CommandTimeout 属性。

    【讨论】:

    • 如果池已饱和,延长超时仅意味着更多请求在等待时排队。它没有解决问题,只会损害网络服务器。让大部分线程阻塞在一个干涸的池中也可能会延迟 GC,从而加剧本已注定的情况。或 tl;博士;版本:不要延长超时时间。
    • 感谢@Marc Gravell 的建议