在从池中获取连接之前经过的超时时间
Posted
技术标签:
【中文标题】在从池中获取连接之前经过的超时时间【英文标题】:The timeout period elapsed prior to obtaining a connection from the pool 【发布时间】:2010-12-11 03:58:13 【问题描述】:我们的网站在一天中 90% 的时间都运行良好,然后在我们的高峰时段流量大约是正常情况的两倍时,一切都会慢下来。通常为 1 秒的页面加载时间需要 30 秒。检查我们的错误日志,看起来可能是连接池问题。我们有 3 个 Web 服务器连接到 1 个 sql server db。 SQL 服务器在所有内核上的利用率都低于 25%。
我查看了我们 SQL 服务器上的用户连接计数器,发现在我们的高峰期我们有 400 多个用户连接,但在非工作时间它大约是 120 多个。
我很确定我们只是使用 MS 提供的任何默认设置来处理我们的应用程序池。我可以做些什么来测试是否是应用程序池问题?将应用程序池大小增加到 1000 有什么负面影响(我该怎么做?)。
谢谢!
【问题讨论】:
什么版本的 ASP.Net 和 SqlServer? 当我第一次看到主题行时,我以为你是救生员。 【参考方案1】:根据我的经验,您可以从 SQL Server 接收到 3 种主要类型的超时:
1) InvalidOperationException
- 客户端在命令字符串中指定的超时(默认 15 秒)之前无法从其自己的池中获取池连接。客户端的池处于其最大大小,并且所有池连接都在使用中,并在超时结束之前保持使用状态。
2) SQLException
- 连接超时。客户端的连接池正在创建与数据库的新连接,但数据库在命令字符串中指定的超时(默认 15 秒)之前没有响应。
3) SQLException
- 命令超时。已获得连接,但 SQL 语句执行命令所用的时间超过了在命令的 CommandTimeout 属性中指定的超时时间(默认 30 秒)
在添加负载之前,您的服务器正常运行的情况听起来像案例 #1。我发现超时非常快 - 通常是 2 秒。
我发现解决方案是增加 SQL Server 中的最大线程数。默认为零 - 让 SQL Server 决定。我见过这样的情况,一个坚固的服务器占用的资源很少,而它通过分配太少的线程来限制自己。
您可以使用此 transact-sql 增加最大线程设置:
sp_configure 'max worker threads', 8192
go
Reconfigure
然后,重新启动您的 SQL 服务。
顺便说一句,您可以使用此命令查看 SQL Server 当前分配了多少线程:
select sum(current_workers_count) from sys.dm_os_schedulers
此线程设置对 SQL Server 在多个连接下的执行方式产生了巨大影响。一旦线程用完,SQL Server 就会变得非常无响应。
【讨论】:
【参考方案2】:这可能与未正确处理(返回池)的 sql 连接有关。确保您拨打的是SqlConnection.Dispose
。
【讨论】:
或者通过将连接放入using() ...
构造来隐式处理。
就我而言,我没有关闭连接。【参考方案3】:
这可能是因为 SQL 连接池已耗尽(这与应用程序池不同。)您可以通过连接字符串通过increasing the pool size 进行检查:
Integrated Security=SSPI;Initial Catalog=northwind;Max Pool Size=100;
但更有可能的是,您的数据库无法跟上传入查询的流。这会导致连接等待其查询结束。添加更多连接将有助于应对突发请求,但对持续的高流量没有帮助。
以下是提高 SQL Server 在持续高负载下的性能的一些建议:
硬件问题(尤其是 SQL Server 上的 RAM) 将 SQL Server Profiler 附加到服务器,跟踪某个高负载时段,并遵循其建议的索引 从跟踪日志中检查长时间运行的查询,并与 T-SQL 开发人员一起改进这些查询祝你好运,这些事情可能非常复杂!
【讨论】:
【参考方案4】:当我收到此错误时:
在从 水池。这可能是因为所有池连接都在 已达到使用和最大池大小
这是因为我使用的是SqlCommand.ExecuteQuery()
方法而不是SqlCommand.ExecuteNonQuery()
。
例如:我原来的存储过程调用看起来像这样:
using (SqlCommand cmd = new SqlCommand())
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "InsertSproc";
cmd.Parameters.AddWithValue("@Value", myValue);
cmd.Parameters.AddWithValue("@LoggedDate", myDate);
DatabaseManager.instance.ExecuteQuery(cmd);
上面的代码是引发异常的原因。但是,将调用更改为使用 ExecuteNonQuery() 解决了问题:
using (SqlCommand cmd = new SqlCommand())
cmd.CommandType = System.Data.CommandType.StoredProcedure;
cmd.CommandText = "InsertSproc";
cmd.Parameters.AddWithValue("@Value", myValue);
cmd.Parameters.AddWithValue("@LoggedDate", myDate);
DatabaseManager.instance.ExecuteNonQuery(cmd);
【讨论】:
【参考方案5】:我在使用 Powershell 和背靠背查询时遇到了这个问题(invoke-sqlcmd,然后是另一个 invoke-sqlcmd)。这两个查询都涉及数据修改。通过在参数调用中添加 -connectiontimeout 1 解决。
例子:
invoke-sqlcmd "insert into testdb..tab1 (cname) select 'x'" -connectiontimeout 1
invoke-sqlcmd "update testdb..tab1 set ctr=ctr+1 where cname='aaa'"
超时长度可能因受影响的行数而异。
【讨论】:
以上是关于在从池中获取连接之前经过的超时时间的主要内容,如果未能解决你的问题,请参考以下文章
超时时间已到。超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。
连接字符串中Min Pool Size的理解是错误,超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。