ADO.NET 中的连接池超时错误
Timeout error in ADO.NET with connection pooling
我们有传统的 SOAP ASP.NET 网络服务,它连接到 SQL 服务器数据库以检索结果集。下面是我们的连接字符串:
connectionString="server=ServerName;database=UserDBName;user id=UserNameRef;Password=myPassword;
我们将命令超时设置为 5 分钟。我们看到的是,我们的 SQL Server 2012 数据库与连接池经常发生超时问题错误。服务器中没有正在进行的主要活动或发生阻塞问题。
来自 sp_whoisactive
跟踪的 PFB 快照。如果我们看到,session 52 在 5 分钟后超时。我们不是 运行 这个 session 中的任何命令。不知道,怎么突然超时了。
如何修复这些超时错误?
+---------+------------+-----------+----------+---------------------------+-------------+---------------------+-------------+------------+------------+-----------------+
| status | session_id | wait_info | sql_text | sql_command | login_name | blocking_session_id | host_name | start_time | login_time | collection_time |
+---------+------------+-----------+----------+---------------------------+-------------+---------------------+-------------+------------+------------+-----------------+
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:00 AM | 2:39:00 AM | 2:39:00 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:06 AM | 2:39:00 AM | 2:39:16 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:39:31 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:39:46 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:40:01 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:40:16 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:40:31 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:40:46 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:41:01 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:41:16 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:41:31 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:41:46 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:42:01 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:42:16 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:42:31 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:42:46 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:43:01 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:43:16 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:43:30 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:43:46 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:44:01 AM | <== Post this timeout occurs
+---------+------------+-----------+----------+---------------------------+-------------+---------------------+-------------+------------+------------+-----------------+
这闻起来像是尚未处理的资源。我可以问你“你是在操作执行后立即处理连接和命令吗?”:
我推荐一个 using
块,它保证在块末尾进行处理,如:
string sqlConnectionString = "...(put the connection string here)...";
string commandText = "...(put the SQL command here)...";
using (var connection = new SqlConnection(sqlConnectionString))
{
using (var command = new SqlCommand(commandText, connection))
{
return command.ExecuteNonQuery();
}
}
另一个问题可能与连接池算法有关,这表明要从池中受益,连接字符串值非常重要:
Only connections with the same configuration can be pooled. ADO.NET keeps several pools at the same time, one for each configuration. Connections are separated into pools by connection string, and by Windows identity when integrated security is used. Connections are also pooled based on whether they are enlisted in a transaction.
我知道你可能已经读过了,但这是文档的 link:SQL Server Connection Pooling (ADO.NET)
请告诉我进展如何!
(按要求移至第一个答案的末尾)
问题中的跟踪与超时问题无关。很抱歉造成的混乱。 超时问题是由于阻塞问题而发生的,其中此 ASP.NET 网络服务正在等待另一个漫长的 运行 SQL 代理作业完成。
As command time out was set as 5 minutes, the SQL agent job was
writing to the background table and was blocking this ASP.NET
webservice call. After being blocked for 5 minutes, the ASP.NET
webservice times out, due to command time out of 5 minutes.
应用的修复:
我们通过分析 long 运行 瓶颈后台作业的执行计划,解决了这个超时问题,通过在两个后台表上将现有的非聚集索引更改为聚集索引,从而使数据检索更快,阻塞发生更少。现在,超时问题已经解决了。
我们有传统的 SOAP ASP.NET 网络服务,它连接到 SQL 服务器数据库以检索结果集。下面是我们的连接字符串:
connectionString="server=ServerName;database=UserDBName;user id=UserNameRef;Password=myPassword;
我们将命令超时设置为 5 分钟。我们看到的是,我们的 SQL Server 2012 数据库与连接池经常发生超时问题错误。服务器中没有正在进行的主要活动或发生阻塞问题。
来自 sp_whoisactive
跟踪的 PFB 快照。如果我们看到,session 52 在 5 分钟后超时。我们不是 运行 这个 session 中的任何命令。不知道,怎么突然超时了。
如何修复这些超时错误?
+---------+------------+-----------+----------+---------------------------+-------------+---------------------+-------------+------------+------------+-----------------+
| status | session_id | wait_info | sql_text | sql_command | login_name | blocking_session_id | host_name | start_time | login_time | collection_time |
+---------+------------+-----------+----------+---------------------------+-------------+---------------------+-------------+------------+------------+-----------------+
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:00 AM | 2:39:00 AM | 2:39:00 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:06 AM | 2:39:00 AM | 2:39:16 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:39:31 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:39:46 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:40:01 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:40:16 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:40:31 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:40:46 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:41:01 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:41:16 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:41:31 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:41:46 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:42:01 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:42:16 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:42:31 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:42:46 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:43:01 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:43:16 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:43:30 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:43:46 AM |
| dormant | 52 | NULL | | sys.sp_reset_connection;1 | UserNameRef | NULL | HostNameRef | 2:39:21 AM | 2:39:00 AM | 2:44:01 AM | <== Post this timeout occurs
+---------+------------+-----------+----------+---------------------------+-------------+---------------------+-------------+------------+------------+-----------------+
这闻起来像是尚未处理的资源。我可以问你“你是在操作执行后立即处理连接和命令吗?”:
我推荐一个 using
块,它保证在块末尾进行处理,如:
string sqlConnectionString = "...(put the connection string here)...";
string commandText = "...(put the SQL command here)...";
using (var connection = new SqlConnection(sqlConnectionString))
{
using (var command = new SqlCommand(commandText, connection))
{
return command.ExecuteNonQuery();
}
}
另一个问题可能与连接池算法有关,这表明要从池中受益,连接字符串值非常重要:
Only connections with the same configuration can be pooled. ADO.NET keeps several pools at the same time, one for each configuration. Connections are separated into pools by connection string, and by Windows identity when integrated security is used. Connections are also pooled based on whether they are enlisted in a transaction.
我知道你可能已经读过了,但这是文档的 link:SQL Server Connection Pooling (ADO.NET)
请告诉我进展如何!
(按要求移至第一个答案的末尾)
问题中的跟踪与超时问题无关。很抱歉造成的混乱。 超时问题是由于阻塞问题而发生的,其中此 ASP.NET 网络服务正在等待另一个漫长的 运行 SQL 代理作业完成。
As command time out was set as 5 minutes, the SQL agent job was writing to the background table and was blocking this ASP.NET webservice call. After being blocked for 5 minutes, the ASP.NET webservice times out, due to command time out of 5 minutes.
应用的修复:
我们通过分析 long 运行 瓶颈后台作业的执行计划,解决了这个超时问题,通过在两个后台表上将现有的非聚集索引更改为聚集索引,从而使数据检索更快,阻塞发生更少。现在,超时问题已经解决了。