"Server=250.65.43.21,4734; Failover_Partner=Partner_B; Database=AdventureWorks; Network=dbmssocn"
连接重试算法(用于 TCP/IP 连接)
对于 TCP/IP 连接,在两个伙伴名称都在缓存中时,数据访问接口遵循连接重试算法。 不论是初次与会话建立连接,还是在中断已建立连接后重新连接,这都适用。 打开连接之后,还需要一些时间完成预登录和登录的步骤。
打开连接所用的时间可能会超过重试时间,这是由于下列外部因素所致:DNS 查找速度缓慢、域控制器/Kerberos 密钥发行中心 (KDC) 速度缓慢、联系 SQL Server Browser 需要时间、网络阻塞等。 此类外部因素可能会阻止客户端连接到镜像数据库。 此外,外部因素还可能会导致打开连接所用的时间长于分配的重试时间。 有关跳过 DNS 和 SQL Server Browser 以尝试连接到初始伙伴的信息,请参阅本主题前面的 建立到数据库镜像会话的初始连接。
如果连接尝试失败或者重试时间过期而未成功重试,则数据访问接口将尝试使用另一个伙伴。 如果此时未打开连接,则数据访问接口还会尝试使用初始伙伴名称和故障转移伙伴名称,直到连接打开或登录期限超时。默认的登录超时期限为 15 秒。 建议登录超时期限至少为 5 秒。 如果指定较短的超时期限,则可能导致连接尝试失败。
重试时间为登录期限的某个百分比数。 在后续的每轮中,连接尝试的重试时间会逐渐变大。 在第一轮中,两次尝试的每次重试时间都是总登录时间的 8%。 在后续的每轮中,重试算法会按相同的百分比增加最大重试时间。 因此,前八次连接尝试的重试时间如下:
8%、8%、16%、16%、24%、24%、32%、32%
重试时间使用以下公式进行计算:
RetryTime = PreviousRetryTime +( 0.08 * LoginTimeout)
其中, PreviousRetryTime 初始值为 0。
例如,如果使用默认的登录超时期限 15 秒,则 LoginTimeout= 15。 在这种情况下,前三轮中分配的重试时间如下:
Round
RetryTime 计算
每次尝试的重试时间
下图说明了这些后续连接尝试的重试时间,每个重试时间均超时。
对于默认的登录超时期限,分配给前三轮连接尝试的最长时间为 14.4 秒。 如果每次尝试都使用了它的全部分配时间,则在登录期限超时之前仅剩下 0.6 秒的时间。在这种情况下,第四轮的时间会缩短,仅允许使用初始伙伴名称进行最后的快速连接尝试。 但是,连接尝试可能会在其分配的重试时间内失败,尤其是在稍后的轮次中。 例如,接收网络错误可能会导致在重试时间到期之前尝试便已结束。 如果较早的尝试因网络错误而失败,则可以为第四轮(还可能包括更多轮)提供更多的时间。
尝试失败的另一个原因是服务器实例处于不活动状态,如同服务器实例执行数据库故障转移时发生的情况。 在这种情况下,可以利用重试延迟时间来防止客户端因快速进行后续连接尝试而导致伙伴重载。
当两个伙伴名称均可用时,如果登录超时期限无限大,则客户端会交替使用初始伙伴名称和故障转移伙伴名称,无限期地尝试重新连接到服务器。
故障转移期间的重试延迟时间
如果客户端尝试连接到进行故障转移的伙伴,则此伙伴会立即做出响应表明它处于不活动状态。 在这种情况下,每轮连接尝试都会比分配的重试时间更短暂。 也就是说,在登录期限超时之前会发生多轮连接尝试。为了避免在故障转移期间因一系列快速的连接尝试而导致伙伴重载,数据访问接口在每次重试循环之后增加了短暂的重试延迟时间。 给定重试延迟时间的长度由重试延迟时间算法确定。 在第一轮之后,延迟时间为 100 毫秒。 在接下来三轮的每轮之后,重试延迟时间加倍,分别达到 200、400 和 800。 对于所有的稍后轮次,重试延迟时间为 1 秒,直到连接尝试成功或超时。
如果服务器实例停止,则连接请求会立即失败。
下图说明了在手动故障转移(其中伙伴会切换其角色)期间重试延迟时间如何影响连接尝试。 登录超时期限为 15 秒。
重新连接到数据库镜像会话
如果已建立的到数据库镜像会话的连接因某种原因(例如,由于数据库镜像故障转移)而失败,但应用程序尝试重新连接到初始服务器,则数据访问接口可以尝试使用客户端缓存中存储的故障转移伙伴名称进行重新连接。 但是,重新连接不是自动进行的, 应用程序必须能够识别错误。 然后,应用程序需要关闭失败的连接并使用相同的连接字符串属性打开新连接。 此时,数据访问接口将连接重定向到故障转移伙伴。 如果由此名称标识的服务器实例当前为主体服务器,则连接尝试通常都会成功。 如果不确定事务已提交还是回滚,则应用程序必须检查事务的状态,检查方法与重新连接到独立服务器实例时所用的方法相同。
重新连接类似于连接字符串为其提供故障转移伙伴名称的初始连接。 如果首次连接尝试失败,则连接尝试会反复轮流使用初始伙伴名称和故障转移伙伴名称,直到客户端连接到主体服务器或数据访问接口超时。
SQL Server Native Client 验证它是否连接到主体服务器实例,但不验证此实例是否为连接字符串初始伙伴名称中指定的服务器实例的伙伴。
如果连接使用 TCP/IP,则连接重试算法将确定为每一轮连接尝试所分配的时间。
如果客户端与数据库断开连接,则数据访问接口不会尝试重新连接。 客户端必须发出新的连接请求。 同样,如果应用程序因中断连接而关闭,则会丢失已缓存的伙伴名称。 如果因为主体服务器不可用而中断连接,则应用程序可重新连接到镜像服务器的唯一方法是在其连接字符串中提供故障转移伙伴名称。
重定向对客户端应用程序的影响
故障转移之后,数据访问接口将连接重定向到当前主体服务器实例。 但是,重定向对客户端是透明的。 对于客户端,重定向的连接似乎是由初始伙伴名称标识的到服务器实例的连接。 初始伙伴当前为镜像服务器时,客户端似乎可以连接到镜像服务器并更新镜像数据库。 但实际上,客户端已重定向到故障转移伙伴(当前主体数据库)并更新新的主体数据库。
重定向到故障转移伙伴之后,客户端在通过 Transact-SQL USE 语句以使用其他数据库时可能会出现意外结果。 如果当前主体服务器实例(故障转移伙伴)具有不同于原始主体服务器(初始伙伴)的一组数据库,则会出现这种情况。
已过时故障转移伙伴名称的影响
数据库管理员可以随时更改故障转移伙伴。 因此,客户端提供的故障转移伙伴名称可能已过时。 例如,假设名为 Partner_B 的故障转移伙伴已由另一个服务器实例 Partner_C 替换。 现在,如果客户端提供 Partner_B 作为故障转移伙伴名称,则该名称已过时。 如果客户端提供的故障转移伙伴名称已过时,数据访问接口的行为与客户端未提供故障转移伙伴名称时的行为相同。
例如,假设客户端使用一个连接字符串连续进行四次连接尝试。 在此连接字符串中,初始伙伴名称为 Partner_A,故障转移伙伴名称为 Partner_B:
"Server=Partner_A; Failover Partner=Partner_B; Database=AdventureWorks"
下表显示了四个伙伴配置,并指示了对于每个配置,此连接字符串是否可以用于与客户端进行第一次连接。
应用程序可以跟踪配置更改并相应地更改其连接字符串。 这要求使用额外的代码但同时要求减轻管理负担。
Partner_B
Partner_A 作为初始伙伴名称保存在缓存中。 客户端成功连接到 Partner_A。 客户端下载镜像服务器的名称 Partner_B 并将其保存在缓存中,同时忽略客户端提供的故障转移伙伴名称。
Partner_A 出现硬件故障,并进行了故障转移(从客户端断开连接)。
Partner_B
Partner_A 仍作为初始伙伴名称保存在缓存中,但却使用客户端提供的故障转移伙伴名称 Partner_B 使客户端连接到当前的主体服务器。
数据库管理员停止镜像(从客户端断开连接),用 Partner_C 替换 Partner_A,然后重新启动镜像。
Partner_B
Partner_C
客户端尝试连接到 Partner_A 并且连接失败,然后客户端尝试连接到 Partner_B(当前的主体服务器)并成功连接。 数据访问接口下载当前镜像服务器 Partner_C 的名称,并将其缓存为当前故障转移伙伴名称。
手动将服务故障转移到 Partner_C(从客户端断开连接)。
Partner_C
Partner_B
客户端最初尝试连接到 Partner_A,然后又尝试连接到 Partner_B,但均未成功。 最后,连接请求超时,无法成功连接。
数据库镜像 (SQL Server)
数据库镜像期间可能出现的故障