排查连接到SQL Server时出现的连接超时错误

适用范围:SQL Server

总结

SQL Server中的“超时过期”错误意味着连接或命令操作未在客户端应用程序允许的超时间隔内完成,因此客户端取消了操作,而不是无限期等待。 本文可帮助你确定是遇到连接超时还是查询或命令超时。 它涵盖了可能会遇到连接超时的错误消息,典型的服务、端口、防火墙和名称解析会导致连接超时。 当客户端应用程序间歇性或一致无法连接到连接超时错误的SQL Server实例时,请使用本文。

若要排查查询或命令超时错误,请参阅 排查查询超时错误

注意

在开始故障排除之前,请检查 先决条件 并浏览清单。

连接到SQL Server时超时过期的错误消息

遇到“超时过期”问题时,会收到以下一条或多条错误消息:

  • 超时时间已到。 超时时间在操作完成或服务器没有响应之前已过。

  • System.Data.SqlClient.SqlException (0x80131904):连接超时已过期。 尝试使用预登录握手确认时超时时长已到。 这可能是因为预登录握手失败,或者服务器无法及时返回响应。 尝试连接到此服务器时花费的持续时间是 [Pre-Login] initialization=23; handshake=14979;
    System.ComponentModel.Win32Exception (0x80004005):等待操作已超时。

  • System.Data.SqlClient.SqlException (0x80131904):超时已过期。 超时时间在操作完成或服务器没有响应之前已过。 System.ComponentModel.Win32Exception (0x80004005):等待操作已超时。

  • 连接超时时间已到。 尝试使用预登录握手确认时超时时长已到。 这可能是因为预登录握手失败,或者服务器无法及时返回响应。
    尝试连接到此服务器的持续时间为 [预登录] 初始化=21036;握手=0;(Microsoft SQL Server,错误: -2)。

  • System.InvalidOperationException:超时已过期。 从池获取连接之前已过超时期限。

    如果连接未正确关闭,则可能会发生错误。 发生这些错误的原因是所有共用连接都正在使用,并且达到最大池大小。 如果遵循连接池文章中已用尽的步骤,可以避免这些错误。 有关池工作原理的详细信息,请参阅SQL Server连接池(ADO.NET)。

注意

安装 .NET Framework 4.5 或更高版本时,会发生第二个和第三个错误。

确定发生哪种类型的超时

数据库应用程序通常观察到两种类型的超时问题:

  • 连接超时(默认为 15 秒)
  • 查询或命令超时(默认为 30 秒)

这两个问题本质上大相径庭,因为它们来自不同来源,在数据库应用程序交互的独立阶段发生。 当与数据库引擎的初始连接失败时,将发生连接超时。 另一方面,查询或命令超时发生在应用程序与数据库服务器交互的生命周期中。 初始连接已成功完成,但提交到数据库服务器的查询需要很长时间才能完成。

在进行故障排除之前,请查看错误消息的完整调用堆栈以确定错误类型。

  • 请参阅连接超时的调用堆栈的以下示例:

    System.Data.SqlClient.SqlException: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
    at System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection)
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
    at System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error)
    at System.Data.SqlClient.TdsParserStateObject.ReadSni(DbAsyncResult asyncResult, TdsParserStateObject stateObj)
    at System.Data.SqlClient.TdsParserStateObject.ReadNetworkPacket()
    at System.Data.SqlClient.TdsParser.ConsumePreLoginHandshake(Boolean encrypt,Boolean trustServerCert, Boolean& marsCapable)
    at System.Data.SqlClient.TdsParser.Connect(ServerInfo serverInfo, SqlInternalConnectionTds connHandler, Boolean ignoreSniOpenTimeout, Int64 timerExpire, Boolean encrypt, Boolean trustServerCert, Boolean integratedSecurity, SqlConnectionowningObject)
    at System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfoserverInfo, String newPassword, Boolean ignoreSniOpenTimeout, Int64 timerExpire, SqlConnection owningObject)
    at System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(String host, String newPassword, Boolean redirectedUserInstance, SqlConnection owningObject, SqlConnectionString connectionOptions, Int64 timerStart)
    at System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(SqlConnection owningObject, SqlConnectionString connectionOptions, String newPassword, Boolean redirectedUserInstance)
    at System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, Object providerInfo, String newPassword, SqlConnection owningObject, Boolean redirectedUserInstance)
    at System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection)
    at System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnection owningConnection, DbConnectionPool pool, DbConnectionOptions options)  
    at System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject) at System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject)
    at System.Data.ProviderBase.DbConnectionPool.GetConnection(DbConnection owningObject)
    at System.Data.ProviderBase.DbConnectionFactory.GetConnection(DbConnection owningConnection)
    at System.Data.ProviderBase.DbConnectionClosed.OpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory)
    at System.Data.SqlClient.SqlConnection.Open()  
    

    SqlConnection.Open 指示客户端正在尝试打开连接,因此与查询无关。

  • 请参阅查询或命令超时的调用堆栈的以下示例:

    System.Data.SqlClient.SqlException: Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
    at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
    at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj)
    at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
    at System.Data.SqlClient.SqlDataReader.ConsumeMetaData()
    at System.Data.SqlClient.SqlDataReader.get_MetaData()
    at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString) at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
    at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
    at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method)
    at System.Data.SqlClient.SqlCommand.ExecuteScalar()
    

    SqlCommand 类用于处理查询,而不是连接。 该方法 ExecuteScalar 用于运行查询。 还可以查看其他项目,例如 ExecuteReaderExecuteNonQuery

    如果遇到查询或命令超时错误,请参阅 排查查询超时错误

排查SQL Server中的连接超时错误

如果遇到连接超时错误,请执行以下步骤:

  1. 增加连接超时参数。

    • 如果使用应用程序连接到 SQL Server,请增加相关的连接超时参数值,并检查连接最终是否成功。 例如,如果使用 System.Data.SqlClient,请将 SqlConnection.ConnectionTimeout 属性设置为 30 或更高的值。 如果使用当前Microsoft。Data.SqlClient 驱动程序,设置等效的 SqlConnection.ConnectionTimeout 属性。

      注意

      如果使用其他提供程序,请检查 主页以执行 SQL 客户端编程

    • 如果使用 SQL Server Management Studio (SSMS),请在“连接到服务器”对话框中选择“连接属性”选项卡,并将“连接超时”设置设置为更高的值。

  2. 如果连接最终成功,则这是一个网络问题。 请与网络管理员协作解决此问题。 解析后,可以还原到应用程序中的默认设置。

    注意

    增加应用程序中的连接超时是一种可能的方法,但它不是长期解决方法。 这是因为尝试连接到数据源时,连接会快速(通常在几毫秒内)发生。

连接超时错误的服务、端口和协议原因

下表列出了SQL Server服务、端口和网络协议导致超时过期错误的原因,以及如何解决每个错误。 有关更多提示和建议,请参阅 故障排除:超时已过期。

典型原因 解决方法
服务器上的 SQL Server 服务未运行。 启动 SQL Server 数据库引擎实例。
数据库引擎实例的 TCP/IP 端口被防火墙阻止。 将防火墙配置为允许访问数据库引擎。
数据库引擎未侦听端口 1433。 这是因为端口已更改,或者不是默认实例,并且 SQL Server Browser 服务未运行。 启动 SQL Server Browser 服务或指定 TCP/IP 端口号以使用 Sqlcmd -S <ip_addres>,<port> 命令进行连接。 在错误日志中,找到 SQL Server 正在侦听的端口号。 有关详细信息,请参阅 配置服务器以侦听特定的 TCP 端口
SQL Server Browser 服务正在运行,但 UDP 端口 1434 被防火墙阻止。 将防火墙配置为允许访问服务器上的 UPD 端口 1434,或指定要连接的 TCP/IP 端口号。
客户端和服务器未配置为使用相同的网络协议。 使用 SQL Server 配置管理器,确保服务器和客户端计算机至少有一个启用的协议。 例如,如果客户端正在使用 TCP/IP 套接字进行连接,但 SQL Server 仅侦听命名管道,则无法建立连接。

连接超时错误的网络和名称解析原因

下表列出了超时过期错误的网络级别原因,例如 DNS 名称解析失败和 TCP/IP 路由问题,以及如何解决每个错误。

典型原因 解决方法
错误地键入了服务器名称。 请使用正确的服务器名称重试。
网络无法将服务器名称解析为 IP 地址。 使用 ping 或 telnet 程序测试此问题。 修复网络上的计算机名称解析问题,或使用 IP 地址连接到服务器。 此问题不是SQL Server问题。 有关帮助,请参阅 Windows 文档或联系网络管理员。 使用以下命令测试连接:
telnet <ServerName> [<Port>]
telnet <IP_Address> <Port>
如果使用 IP 地址有效,但服务器名称不起作用,则这是名称解析问题。
网络无法使用 IP 地址进行连接。 使用 ping、telnet 或 tracert 程序测试此问题。 修复网络上的 TCP/IP 问题。 此问题不是SQL Server问题。 有关帮助,请参阅 Windows 文档或联系网络管理员。
有关更高级的网络故障排除,请参阅 0300 间歇性或定期网络问题