偶发SQL连接超时

时间:2013-06-19 13:40:12

标签: sql-server

我们在连接到远程安装的MSSQL 2012实例的计算机上部署了一些应用程序。除一个应用程序外,它们在本地管理员帐户下作为Windows服务运行。 客户端在Windows 7 32位上运行,而数据库在Windows Server 2008 R2 64位上运行。

我在四次连接尝试中有一次出现此错误:

SqlException (0x80131904): A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: TCP Provider, error: 0 - A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
   bei System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
   bei System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
   bei System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity)
   bei System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, SqlConnection owningObject)
   bei System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, Boolean redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, TimeoutTimer timeout)
   bei System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject, TimeoutTimer timeout, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance)
   bei System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance)
   bei System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection)
   bei System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options)
   bei System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject)
   bei System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject)
   bei System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
   bei System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
   bei System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
   bei System.Data.SqlClient.SqlConnection.Open()

我在所有应用程序中使用此连接字符串:

  

Data Source = 192.168.0.101 \ NAMEDINSTANCE; Initial Catalog = database; Integrated Security = False; Persist Security Info = False; User ID = user; Password = password

我使用无限的ping请求检查了网络连接但是在发生错误时它没有问题。 首先我得到了一个类似的错误消息,而NamedPipes被启用,但在停用NamedPipes(我们没有使用它)后,上述错误发生在同一频率。 相同的设置正在其他机器上运行。 错误在几周前开始发生,在它成功运行约3个月之前。这是一个离线设置,系统自部署后未更新(但我无法保证)。 两台机器上的防火墙都关闭了。 Windows上没有提示,也没有SQL-Server事件日志。 我还更换了网线以排除断线。

我现在有点陷入困境,因为我不知道接下来要去哪里。也许有一些可用的连接字符串调整,或者我可以更改一些配置服务器或客户端。

更新 使用granadaCoders帮助我发现tcp调用可能会被某些东西过滤掉。我使用PortQry来检查它。

portqry -n 192.168.0.101 -e 1433 -p tcp
TCP port 1433 (ms-sql-s service): FILTERED

如果这种情况一直发生,我会说防火墙阻止我的呼叫,但在这种情况下,它可能是某种系统过载导致我的请求丢失。 接下来要做的是通过连接特定端口来检查它是否是SQL Server Browser故障。然后更换开关。

更新(2013-07-03):我写了一个测试应用程序,它每秒打开一个连接并在故障系统上运行它。有效。我在几个连接中两次在其他应用程序上得到了错误,但是在我的测试应用程序中的500个连接中没有设法得到它。

更新(2013-07-05:我忘记了这个服务器还有另一个网络连接。几周前已连接。看起来这是导致此问题的根本原因。

4 个答案:

答案 0 :(得分:2)

  1. 阅读this
  2. 您可以定义要使用in the connection string的网络库。 dbmssocn是我的首选。
  3. 可能将端口添加到连接字符串。
  4. 当您使用IP地址时,请指定端口号并将其提供给网络库,这就像我认为的那样“非常具体”。

    查看Connect via IP address示例。

答案 1 :(得分:0)

很难说它来自何处,但是使用连接字符串中的端口而不是命名实例的选项?

如果使用命名实例,则第一个请求将转到目标系统上的SQL Server Browser(在端口1434上运行)以获取与命名实例关联的端口。只有这样才能与指定的端口建立真正的连接。如果您直接使用该端口,则会消除此往返,如果您在任何地方使用该端口,您还可以通过关闭SQL Server浏览器来减少攻击面。

答案 2 :(得分:0)

检查您的开发者始终是否使用try/finallyusing块进行连接。通常你会看到这样的代码:

SqlConnection con = ... ;
con.Open();

// ... use the connection ...

con.Close();

该代码错误。如果在该代码中间发生异常,则永远不会执行con.Close();行。这会导致连接保持打开状态,如果这种情况经常发生,您可以最大化服务器上​​允许的活动连接数,将自己锁定在服务器之外,并获得与您发布的类似的异常跟踪。

相反,您需要始终使用using块或try / finally包裹您的连接:

using (SqlConnection con = ... )
{
    con.Open();

    // ... use the connection ...
}

请注意,我甚至不需要在这里调用con.Close(),因为using块为我处理了它。另一种选择:

SqlConnection con = ... ;
try 
{    
    con.Open();

    // ... use the connection ...
}
finally
{
    con.Close();
}

答案 3 :(得分:0)

服务器和客户端都通过两个独立的网络连接。当我通过网络A发送连接请求时,似乎SQL Server可能通过网络B回答它。

在Windows(A over B)中正确设置了网络优先级。

解决了我的问题是改变了服务器上的两根网线。现在不再有超时,一切都按预期工作。 服务器主板上有两个连接器,但似乎忽略了Windows的优先设置。

在SQL Server TCP配置中禁用了网络B,因此无论如何都不应该使用它。这对我来说是一种奇怪的行为,因为我找不到可能发生这种情况的原因。