KB328476 - 禁用SQL Server连接池时可能需要调整的 TCP/IP 设置的说明

应用对象
Microsoft SQL Server 2005 Standard Edition Microsoft SQL Server 2005 Developer Edition Microsoft SQL Server 2005 Enterprise Edition Microsoft SQL Server 2005 Express Edition Microsoft SQL Server 2005 Workgroup Edition

摘要

使用 SQL Server ODBC 驱动程序、SQL Server OLE DB 提供程序或 System.Data.SqlClient 托管提供程序时,可以通过使用相应的应用程序编程接口 (API) 来禁用连接池。 禁用池时,如果应用程序经常打开和关闭连接,则基础SQL Server网络库的压力可能会增加。 本文介绍在这些条件下可能需要调整的某些 TCP/IP 设置。

详细信息

关闭池可能导致基础SQL Server网络驱动程序快速打开和关闭与运行 SQL Server 的计算机的新套接字连接。 可能需要更改操作系统和运行SQL Server的计算机的默认 TCP/IP 套接字设置,以处理更高的压力级别。

请注意,本文仅讨论在使用 TCP/IP 协议时影响SQL Server网络库的设置。 关闭池也可能导致其他SQL Server协议(如命名管道)出现压力相关问题,但本文不讨论本主题。 本文仅适用于高级用户。 如果你不了解本文中的主题,Microsoft建议你查看一本关于 TCP/IP 套接字的好书。

请注意,Microsoft强烈建议始终将池与SQL Server驱动程序一起使用。 使用 SQL Server 驱动程序时,使用池可显著提高客户端和SQL Server端的整体性能。 使用池化还可以大幅减少流向运行SQL Server的计算机的网络流量。 例如,使用 20,000 个SQL Server连接的示例测试在启用池的情况下打开和关闭,使用了大约 160 个 TCP/IP 网络数据包,总共有 23,520 字节的网络活动。 在禁用池的情况下,同一示例测试生成了 225,129 个 TCP/IP 网络数据包,总共 27,209,622 字节的网络活动。

请注意,当你看到这些与SQL Server网络库相关的与压力相关的 TCP/IP 套接字问题时,在尝试连接到运行SQL Server的计算机时,可能会收到以下一个或多个错误消息:

注意

不存在SQL Server或访问被拒绝

注意

超时已过期

注意

常规网络错误

注意

TCP 提供程序:通常只允许使用每个套接字地址 (协议/网络地址/端口) 。

请注意,当SQL Server出现其他问题时,你也可能收到这些特定的错误消息;例如,如果运行SQL Server的远程计算机已关闭,如果运行SQL Server的远程计算机根本不侦听 TCP/IP 套接字,如果与正在运行的计算机的网络连接,则可能会收到这些错误消息SQL Server中断,因为已拔出网线,或者遇到 DNS 解析问题。 基本上,任何可能导致客户端无法打开运行SQL Server计算机的 TCP/IP 套接字也可能导致错误消息。 但是,对于与压力相关的套接字问题,当压力上升和下降时,该问题会间歇性地发生。 计算机可以运行数小时,没有错误,然后错误发生一两次,然后计算机再运行几个小时,没有错误。 此外,遇到此问题时,与SQL Server的常规连接一次性运行,下一个连接会失败,然后在下一刻再次工作。 换句话说,与压力相关的套接字问题通常偶尔发生,但SQL Server的实际网络连接问题通常不会偶尔发生。

在使用SQL Server TCP/IP 协议时禁用池时,通常会发生两个主要与压力相关的问题:客户端计算机上的匿名端口可能耗尽,或者可能超出运行 SQL Server 的计算机上的默认 WinsockListenBacklog 设置。

有关匿名端口的其他信息,请单击下面的文章编号以查看Microsoft知识库中的文章:

319502 PRB:增加 IMAP 连接限制后尝试通过匿名端口进行连接时出现“WSAEADDRESSINUSE”错误消息

调整 MaxUserPort 和 TcpTimedWaitDelay 设置

请注意,MaxUserPort 和 TcpTimedWaitDelay 设置仅适用于正在快速打开和关闭与运行 SQL Server 且未使用连接池的远程计算机的连接。 例如,这些设置适用于 Internet Information Services (IIS) 服务器,该服务器正在为大量传入 HTTP 请求提供服务,并且正在打开和关闭与运行SQL Server且使用 TCP/IP 协议并禁用池的远程计算机的连接。 如果启用了池化,则无需调整 MaxUserPort 和 TcpTimedWaitDelay 设置。

使用 TCP/IP 协议打开与运行 SQL Server 的计算机的连接时,基础SQL Server网络库将打开运行 SQL Server 的计算机的 TCP/IP 套接字。 打开此套接字时,SQL Server网络库不会启用SO_REUSEADDR TCP/IP 套接字选项。 有关SO_REUSEADDR套接字设置的详细信息,请参阅Microsoft开发人员网络 (MSDN) 中的“Setsockopt”主题。

请注意,出于安全原因,SQL Server网络库不会专门启用SO_REUSEADDR TCP/IP 套接字选项。 启用SO_REUSEADDR后,恶意用户可以劫持客户端端口以SQL Server并使用客户端提供的凭据来访问运行SQL Server的计算机。 默认情况下,由于SQL Server网络库不启用SO_REUSEADDR套接字选项,因此每次通过客户端上的SQL Server网络库打开和关闭套接字时,套接字将进入TIME_WAIT状态四分钟。 如果在禁用池的情况下快速打开和关闭SQL Server TCP/IP 连接,则会快速打开和关闭 TCP/IP 套接字。 换句话说,每个SQL Server连接都有一个 TCP/IP 套接字。 如果在不到 4 分钟内快速打开和关闭 4000 个套接字,则会达到客户端匿名端口的默认最大设置,并且新的套接字连接尝试将失败,直到现有TIME_WAIT套接字集超时。

在客户端上,禁用池时,可能需要增加 Q319502 中讨论的 MaxUserPort 和 TcpTimedWaitDelay 设置。 这些值的设置取决于客户端上发生的连接打开和关闭SQL Server数。 可以使用客户端计算机上的 Netstat 工具检查处于TIME_WAIT状态的客户端端口数。 按如下所示使用 -n 标志运行 Netstat 工具,并计算SQL Server IP 地址处于TIME_WAIT状态的客户端套接字数。 在此示例中,运行SQL Server的远程计算机的 IP 地址为 10.10.10.20,客户端计算机的 IP 地址为 10.10.10.10,三个已建立的连接和两个连接处于TIME_WAIT状态:

C:\>netstat -n

Active Connections

  Proto  Local Address         Foreign Address       State
  TCP    10.10.10.10:2000      10.10.10.20:1433      ESTABLISHED
  TCP    10.10.10.10:2001      10.10.10.20:1433      ESTABLISHED
  TCP    10.10.10.10:2002      10.10.10.20:1433      ESTABLISHED
  TCP    10.10.10.10:2003      10.10.10.20:1433      TIME_WAIT
  TCP    10.10.10.10:2004      10.10.10.20:1433      TIME_WAIT

如果运行 netstat -n,并且看到与运行 SQL Server 的目标计算机的 IP 地址的近 4000 个连接处于TIME_WAIT状态,则可以同时增加默认 MaxUserPort 设置并减少 TcpTimedWaitDelay 设置,以免客户端匿名端口耗尽。 例如,可以将 MaxUserPort 设置设置为 20000,并将 TcpTimedWaitDelay 设置设置为 30。 较低的 TcpTimedWaitDelay 设置意味着套接字在TIME_WAIT状态中等待的时间更少。 较高的 MaxUserPort 设置意味着可以拥有更多处于TIME_WAIT状态的套接字。

请注意,如果调整 MaxUserPort 或 TcpTimedWaitDelay 设置,则必须重启Microsoft Windows 才能使新设置生效。 MaxUserPort 和 TcpTimedWaitDelay 设置适用于通过 TCP/IP 套接字与运行SQL Server的计算机通信的任何客户端计算机。 如果在运行SQL Server的计算机上设置这些设置,除非与运行SQL Server的本地计算机建立本地 TCP/IP 套接字连接,否则这些设置将不起作用。

注意 如果调整 MaxUserPort 设置,建议保留端口 1434 供SQL Server浏览器服务 (sqlbrowser.exe) 使用。 有关如何执行此操作的详细信息,请单击下面的编号以查看Microsoft知识库中的文章:

812873如何在运行 Windows Server 2003 或 Windows 2000 Server 的计算机上保留一系列临时端口

调整 WinsockListenBacklog 设置

有关此特定于SQL Server注册表设置的其他信息,请单击下面的序列号以查看Microsoft知识库中的文章:

154628 INF:具有多个 TCP\IP 连接请求的 SQL 日志 17832
当SQL Server网络库侦听 TCP/IP 套接字时,SQL Server网络库使用侦听 Winsock API。 侦听 API 的第二个参数是套接字允许的积压工作。 此积压工作表示侦听器挂起连接队列的最大长度。 当队列的长度超过此最大长度时,SQL Server网络库会立即拒绝更多 TCP/IP 套接字连接尝试。 此外,SQL Server网络库发送 ACK+RESET 数据包。

SQL Server 2000 使用默认侦听积压工作设置 5。 这意味着,当侦听 API 在运行 SQL Server 的计算机上设置 TCP/IP 协议侦听线程时,运行 SQL Server 的计算机将值 5 传递给侦听 Winsock API 的积压工作参数。 可以调整 WinsockListenBacklog 注册表项,以指定要为此参数传递的其他值。 从 SQL Server 2005 开始,网络库将 SOMAXCONN 值作为积压工作设置传递给侦听 API。 SOMAXCONN 允许 Winsock 提供程序为此设置设置最大合理值。 因此,SQL Server 2005 中不再使用或不再需要 WinsockListenBacklog 注册表项。

积压工作设置的工作方式如下:假设任意服务正在侦听传入的 TCP/IP 套接字请求。 如果将积压工作设置设置为 5,并且许多套接字连接请求不断流式传入,则服务可能无法像传入请求那样快速响应传入请求。 此时,TCP/IP 套接字层将这些传入请求排入积压工作队列,服务稍后可以从此队列中拉取请求并处理传入套接字连接请求。 队列填满后,TCP/IP 套接字层会立即拒绝传入的任何其他套接字请求,方法是将 ACK+RESET 数据包发送回客户端。 增加积压工作队列大小会增加 TCP/IP 套接字层在请求被拒绝前排队的挂起套接字连接请求数。

请注意,WinsockListenBacklog 设置特定于SQL Server。 SQL Server尝试在SQL Server服务首次启动时读取此注册表设置。 如果该设置不存在,则使用默认值 5。 如果注册表设置存在,SQL Server读取设置,并在调用 WinSock API 侦听时使用提供的值作为积压工作设置,因为 TCP/IP 套接字侦听线程是在SQL Server内设置的。

若要确定是否遇到此问题,可以在客户端或运行 SQL Server 的计算机上运行网络监视器跟踪,并查找 ACK+RESET 立即拒绝的套接字连接请求。 如果在网络监视器中检查 TCP/IP 数据包,则发生此问题时会看到如下所示的数据包:

Frame: Base frame properties
ETHERNET:  EType = Internet IP (IPv4) 
IP: Protocol = TCP - Transmission Control; Packet ID = 40530; Total IP Length = 40; Options = No Options
TCP: Control Bits: .A.R.., len:    0, seq:         0-0, ack:3409265780, win:    0, src: 1433  dst: 4364 
  TCP: Source Port = 0x0599
  TCP: Destination Port = 0x110C
  TCP: Sequence Number = 0 (0x0)
  TCP: Acknowledgement Number = 3409265780 (0xCB354474)
  TCP: Data Offset = 20 bytes
  TCP: Flags = 0x14 : .A.R..
    TCP: ..0..... = No urgent data
    TCP: ...1.... = Acknowledgement field significant
    TCP: ....0... = No Push function
    TCP: .....1.. = Reset the connection
    TCP: ......0. = No Synchronize
    TCP: .......0 = Not the end of the data
  TCP: Window = 0 (0x0)
  TCP: Checksum = 0xF1E7
  TCP: Urgent Pointer = 0 (0x0)

请注意,源端口0x599,或 1433(以十进制为单位)。 这意味着数据包来自运行 SQL Server并在默认端口 1433 上运行的典型计算机。 另请注意,已设置“确认”字段和“重置连接”标志。 如果熟悉筛选网络监视器跟踪,可以通过0x14十六进制来筛选 TCP 标志值,以便仅查看网络监视器跟踪中的 ACK+RESET 数据包。

请注意,如果运行SQL Server的计算机根本不在运行,或者运行SQL Server的计算机未侦听 TCP/IP 协议,则你也可以看到类似的 ACK+RESET 数据包,因此,如果看到 ACK+RESET 数据包并不明确确认你遇到了此问题。 如果 WinsockListenBacklog 太低,则某些连接尝试接收接受数据包,而某些连接会立即在同一时间范围内接收 ACK+RESET 数据包。

请注意,在极少数情况下,即使客户端计算机上启用了池,也可能需要调整此设置。 例如,如果许多客户端计算机正在与运行SQL Server的单台计算机通信,则即使启用了池化,也可能会在任何特定时间同时进行大量传入连接尝试。

注意 如果调整 WinsockListenBacklog 设置,则无需重启 Windows 即可使此设置生效。 只需停止并重启SQL Server服务,设置就会生效。 WinsockListenBacklog 注册表设置仅适用于运行 SQL Server 的计算机。 它对与SQL Server通信的任何客户端计算机没有任何影响。