SqlConnection 立即超时
SqlConnection timing out instantly
编写一个非常简单的工具来 ping SQL 服务器并确保可以访问一堆连接字符串,我遇到了一个非常奇怪的问题:在迭代几十个连接字符串时,第一个在我指定的大约多少秒(在这种特殊情况下为 11 秒)并记录相应的尝试和异常当前墙时间后,有六个超时,但突然之间大约有十几个立即超时,然后恢复正常超时。
这是一台机器上的 运行,它无法访问所有要测试的连接字符串中使用的一个 IP。在日志中它看起来像这样:
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:54 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:54 Connection name:
2018-04-06 15:59:54 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:54 Connection name:
2018-04-06 16:00:08 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 16:00:08 Connection name:
2018-04-06 16:00:22 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 16:00:22 Connection name:
2018-04-06 16:00:35 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 16:00:35 Connection name:
2018-04-06 16:00:49 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
看看在一连串的即时超时后,在 15:59:40 记录的最后一个条目在 15:59:54 超时,这是正常的,然后另一个连接立即超时,16:00:08 之后的所有内容再次正常超时。
代码在我看来完全是天真的教科书:
foreach (ConnectionStringSettings cs in ConfigurationManager.ConnectionStrings)
{
if (cs.Name.Equals("LocalSqlServer") && !args.Contains("NoSkipLocal", StringComparer.OrdinalIgnoreCase)) continue;
SqlConnectionStringBuilder b = new SqlConnectionStringBuilder(cs.ConnectionString)
{
ConnectTimeout = timeout == 0 ? 10 : timeout
};
SqlConnection conn = new SqlConnection(b.ConnectionString);
try
{
conn.Open();
LogToConsole("Connection success", ConsoleColor.Green);
}
catch (SqlException sex)
{
LogToConsole("SQL Error:" + sex.Message, ConsoleColor.Red);
}
catch (Exception ex)
{
LogToConsole("Error:" + ex.Message, ConsoleColor.Red);
}
static void LogToConsole(string message, ConsoleColor color = ConsoleColor.Gray)
{
ConsoleColor fgColor = Console.ForegroundColor;
Console.ForegroundColor = color;
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\t" + message);
Console.ForegroundColor = fgColor;
}
其他人是否遇到过 ADO.NET SqlConnection 对象的即时超时?我原以为连接失败很可能是即时的,但至少消息应该有所不同。但它与过去 ~14 秒时完全相同。
将 Pooling = false
添加到连接字符串构建器实例化解决了这个问题。现在每个连接在抛出异常之前等待指定的秒数。
在连接池打开时处理 SqlConnection
是不够的,ADO.NET 池仍然持有特定数据库的条目并存储最后的错误状态,所以当下一个连接对象实例化时连接字符串指向相同,连接超时立即返回。
在我的特定情况下,这是一个很好的行为,因为它节省了我测试连接字符串的时间,但在现实世界中,它可能代表讨厌的副作用。
编写一个非常简单的工具来 ping SQL 服务器并确保可以访问一堆连接字符串,我遇到了一个非常奇怪的问题:在迭代几十个连接字符串时,第一个在我指定的大约多少秒(在这种特殊情况下为 11 秒)并记录相应的尝试和异常当前墙时间后,有六个超时,但突然之间大约有十几个立即超时,然后恢复正常超时。
这是一台机器上的 运行,它无法访问所有要测试的连接字符串中使用的一个 IP。在日志中它看起来像这样:
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:40 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:40 Connection name:
2018-04-06 15:59:54 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:54 Connection name:
2018-04-06 15:59:54 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 15:59:54 Connection name:
2018-04-06 16:00:08 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 16:00:08 Connection name:
2018-04-06 16:00:22 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 16:00:22 Connection name:
2018-04-06 16:00:35 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
2018-04-06 16:00:35 Connection name:
2018-04-06 16:00:49 SQL Error:Connection Timeout Expired. Th
or the server was unable to respond back in time. The duration s
看看在一连串的即时超时后,在 15:59:40 记录的最后一个条目在 15:59:54 超时,这是正常的,然后另一个连接立即超时,16:00:08 之后的所有内容再次正常超时。
代码在我看来完全是天真的教科书:
foreach (ConnectionStringSettings cs in ConfigurationManager.ConnectionStrings)
{
if (cs.Name.Equals("LocalSqlServer") && !args.Contains("NoSkipLocal", StringComparer.OrdinalIgnoreCase)) continue;
SqlConnectionStringBuilder b = new SqlConnectionStringBuilder(cs.ConnectionString)
{
ConnectTimeout = timeout == 0 ? 10 : timeout
};
SqlConnection conn = new SqlConnection(b.ConnectionString);
try
{
conn.Open();
LogToConsole("Connection success", ConsoleColor.Green);
}
catch (SqlException sex)
{
LogToConsole("SQL Error:" + sex.Message, ConsoleColor.Red);
}
catch (Exception ex)
{
LogToConsole("Error:" + ex.Message, ConsoleColor.Red);
}
static void LogToConsole(string message, ConsoleColor color = ConsoleColor.Gray)
{
ConsoleColor fgColor = Console.ForegroundColor;
Console.ForegroundColor = color;
Console.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "\t" + message);
Console.ForegroundColor = fgColor;
}
其他人是否遇到过 ADO.NET SqlConnection 对象的即时超时?我原以为连接失败很可能是即时的,但至少消息应该有所不同。但它与过去 ~14 秒时完全相同。
将 Pooling = false
添加到连接字符串构建器实例化解决了这个问题。现在每个连接在抛出异常之前等待指定的秒数。
在连接池打开时处理 SqlConnection
是不够的,ADO.NET 池仍然持有特定数据库的条目并存储最后的错误状态,所以当下一个连接对象实例化时连接字符串指向相同,连接超时立即返回。
在我的特定情况下,这是一个很好的行为,因为它节省了我测试连接字符串的时间,但在现实世界中,它可能代表讨厌的副作用。