摘要
使用 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通信的任何客户端计算机没有任何影响。