在从池中获取连接之前经过的超时时间

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的理解是错误,超时时间已到,但是尚未从池中获取连接。出现这种情况可能是因为所有池连接均在使用,并且达到了最大池大小。

SQL连接池超时

实体框架中的连接泄漏

数据库连接池问题 Max Pool Size

C# System.InvalidOperationException on sqlconnection close