【发布时间】:2012-10-19 11:14:09
【问题描述】:
我试图了解 MS 企业库的数据访问块如何管理其与 SQL 的连接。我遇到的问题是,在稳定的负载下(来自负载测试),每隔 10 分钟,到 SQL 的连接数会迅速增加 - 这会导致网站的页面响应时间明显增加。
这是我正在运行的场景:
- Visual Studio 负载测试工具,针对负载平衡器后面的 3 个 Web 服务器运行
- 这些工具可让您全面了解所有 Web + DB 盒的性能计数器
- 每个测试大约需要 10 秒,并执行 4 次插入(表单数据)和一些琐碎的选择
- 有 60 个测试同时运行。整个测试过程中负载没有增加或减少。
- 测试运行 20 分钟到 3 小时,结果一致。
这就是我们看到的问题:
- 每 10 分钟,SQL General: User Connections 的 SQL 性能计数器就会增加 - 总共增加约 20 个连接
- 执行 HTTP 发布/数据库插入的页面受影响最大。其他页面显示适度但明显的上升。
- Web 服务器上的 CPU/内存负载不受影响
- 这种增加对应于页面响应时间的显着增加 - 例如。从平均 0.3 秒到最多 5 秒
- 大约 5 分钟后,它会释放许多连接,而不会影响 Web 性能
- 接下来 5 分钟的测试给出了相同(正常)的网络性能
- 最终,图表看起来像square wave
- 在第一次上升 10 分钟后再次发生
我看过的内容:
数据库调用:
数据库中的所有调用都以:
SqlDatabase database = new SqlDatabase([...]);
然后执行任一过程,不需要输出:
return database.ExecuteScalar([...], [...]);
或者读取包装在 using 语句中:
using (SqlDataReader reader = (SqlDataReader)database.ExecuteReader([...], [...]))
{
[...]
}
没有直接使用 SqlConnection,没有 .Open() 或 .Close() 方法,也没有抛出异常
数据库验证:
我们对登录/注销事件运行 SQL 分析器,并使用 sp_who2 命令拍摄快照,显示谁拥有连接。后者表明确实是网站(通过机器 + 凭据看到)正在保持连接。
没有计划的作业(DB 或 Web 服务器),并且当 Web 服务器没有负载时,用户连接负载是稳定的。
连接池配置
我知道连接池的最小和最大大小可以通过连接字符串进行更改。
例如:
"数据源=[服务器];初始目录=[x];集成安全=SSPI;最大 池大小=75;最小池大小=5;"
后备措施可能是将最小尺寸设置为 ~10
我了解默认最大值为 100,默认最小值为 0 (from here)
想到连接池(特定于此设置)和 SQL 中的用户连接性能计数器,我有点轻率。 This article 介绍这些连接池用于管理连接字符串,这似乎与我假设的不同(持有一个通常可用的连接池,以避免在 SQL 上重新打开它们的成本)
我还没有看到任何配置参数可以轻松默认为 5 或 10 分钟,在开始时为零...
因此,感谢任何帮助。
我知道 10 分钟的峰值听起来像是负载变化,或者正在发生新的活动 - 但我们已经非常努力地隔离这些和任何其他因素 - 对于这个问题,我希望了解 EL 扩展其上下连接。
谢谢。
【问题讨论】:
-
我在快速检查 (tldr;) 时看到的是,当您返回标量时,您正在泄漏连接。你必须做:对象标量;使用 (var db = ...) { 标量 = db.Execute(...); } 返回标量;哦……而且你可能也在你的阅读器周围泄露连接。您只将阅读器包裹在 using() 中,而不是连接。你可能想研究一个自动管理你的连接的 IoC,比如nblumhardt.com/2011/01/an-autofac-lifetime-primer
标签: c# sql-server-2008 enterprise-library connection-pooling