【问题标题】:Sporadic SQL Connection Timeouts零星的 SQL 连接超时
【发布时间】:2013-07-05 21:54:41
【问题描述】:

我们在一台机器上部署了一些应用程序,这些应用程序连接到远程安装的 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:我忘记了此服务器还有另一个网络连接。该连接是几周前连接的。看起来这是此问题的根本原因。

【问题讨论】:

  • 你为什么要在这上面标记 C#??
  • 但是你谈论的只是网络、SQL Server 和策略,所以除非是特定的 C# 问题,否则请不要标记 C#
  • @JoelCoehoorn 不太可能,这几乎可以肯定是网络配置或集群服务器问题。不太可能需要更改 C# 代码,甚至是 SQL Server 实例本身。他们最多可能需要更改连接字符串。但是我已经看到这种事情数千次了,90% 的时间是网络上的某些东西阻塞连接的问题,另外 10% 的问题通常是集群/场能够正确地为请求提供服务的问题.
  • 可能知道,但 OP 可能不知道。是的,在确认它确实不是 C# 问题后,重新标记问题,但不要对 OP 标记错误感到愤怒。排除故障的首要规则之一是不要忽视任何可能导致问题的因素。
  • 我再次删除了 C# 标签,因为它会将答案引向错误的方向。关于如何正确建立 sql 连接的答案可能会解决类似的问题,但不是我在这里寻找的。​​span>

标签: sql-server


【解决方案1】:
  1. 阅读this
  2. 您可以定义网络库以使用in the connection stringdbmssocn 是我的首选。
  3. 也许将端口添加到连接字符串中。

当您使用 IP 地址时,指定端口号并为其提供网络库,我认为这是“非常非常具体”。

查看Connect via IP address 示例。

【讨论】:

  • @1: 两台机器都关闭了防火墙@2+3: 错误依旧:(
  • 获取这个工具,并做一些 ip-port "ping" 测试.......这至少会从等式中消除 sql server。 microsoft.com/en-us/download/details.aspx?id=24009
  • 已经这样做了几次portqry -n 192.168.0.101 -e 1433 -p tcp。得到两个不同的回复TCP port 1433 (ms-sql-s service): LISTENING 和一次TCP port 1433 (ms-sql-s service): FILTERED
  • 那么问题不在于我们的 sql server 连接字符串或 sql server。你的网络有点奇怪。
  • FILTERED 此响应表明目标端口正在被过滤。 PortQry 未收到来自目标端口的响应。进程可能正在或可能不在目标端口上侦听。默认情况下,PortQry 在返回 FILTERED 响应之前查询 TCP 端口 3 次,在返回 FILTERED 响应之前查询 UDP 端口一次。
【解决方案2】:

很难说这是从哪里来的,但是在连接字符串中使用端口而不是命名实例是一个选项吗?

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

【讨论】:

    【解决方案3】:

    检查您的开发人员始终使用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();
    }
    

    【讨论】:

    • 我同意你的回答,在一些重启后会出现问题,但也可能在第一次连接时重启客户端后出现。
    【解决方案4】:

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

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

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

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

    【讨论】:

      猜你喜欢
      • 2011-07-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-06-20
      • 2020-07-08
      相关资源
      最近更新 更多