Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
在本篇博文中,我将为大家介绍一个在使用数据库镜像功能时发生的连接超时问题。关于数据库镜像的关键概念和术语,在之前的博客数据库镜像故障转移后,.NET应用程序连接SQL Server 超时(译文)中已经有了详细的介绍,这里不再赘述,大家可以参考前文。
问题描述
========
客户想要在Lync上安装一些组件,在后端需要从英国站点向澳大利亚站点的SQL Server建立连接时会如下错误:

英国站点:
服务器: lyncdben01
澳大利亚站点:
服务器: lyncdbau01
在问题调查的过程中,我们分别收集到了连接成功时与问题发生时的Netmon 日志。从dump 文件中,得到了Powershell命令背后真正的连接字符串:
Data Source= lyncdbau01.group.local\lyncdbau01;Database=xds;Max Pool Size=4;Connection Reset =false;Enlist=false;IntegratedSecurity=true;Pooling=true;Failover Partner= lyncdbau02.group.local\lyncdbau02;
问题分析
=========
1. 连接字符串很明确的告诉了我们,这是一个用于连接使用了镜像的数据库的连接字符串。如果一个连接尝试失败或者重试时间过期,则数据访问接口将尝试连接镜像的另一个伙伴。如果此时未打开连接,则数据访问接口还会尝试使用初始伙伴名称和故障转移伙伴名称,直到连接打开或登录期限超时。
重试时间为登录期限的某个百分比数。在后续的每轮中,连接尝试的重试时间会逐渐变大。在第一轮中,两次尝试的每次重试时间都是总登录时间的 8%。在后续的每轮中,重试算法会按相同的百分比增加最大重试时间。因此,前八次连接尝试的重试时间如下:
8%, 8%, 16%, 16%, 24%, 24%, 32%, 32%
重试时间使用以下公式进行计算:
RetryTime = PreviousRetryTime + ( 0.08*LoginTimeout)
其中,PreviousRetryTime 初始值为 0。
例如,如果使用默认的登录超时期限 15 秒,则LoginTimeout = 15。在这种情况下,前三轮中分配的重试时间如下:
轮次 |
RetryTime 计算 |
每次尝试的重试时间 |
1 |
0 +(0.08 * 15) |
1.2 秒 |
2 |
1.2 +(0.08 * 15) |
2.4 秒 |
3 |
2.4 +(0.08 * 15) |
3.6 秒 |
4 |
3.6 +(0.08 * 15) |
4.8 秒 |
下图说明了这些后续连接尝试的重试时间,每个重试时间均超时。
对于默认的登录超时期限,分配给前三轮连接尝试的最长时间为14.4 秒。如果每次尝试都使用了它的全部分配时间,则在登录期限超时之前仅剩下 0.6 秒的时间。在这种情况下,第四轮的时间会缩短,仅允许使用初始伙伴名称进行最后的快速连接尝试。但是,连接尝试可能会在其分配的重试时间内失败,尤其是在稍后的轮次中。例如,接收网络错误可能会导致在重试时间到期之前尝试便已结束。如果较早的尝试因网络错误而失败,则可以为第四轮(还可能包括更多轮)提供更多的时间。
(https://msdn.microsoft.com/en-us/library/ms365783.aspx )
2. 此时分析抓取到的Netmon日志会发现在问题发生时,客户端很快就close并reset了连接:
434 10:32:00 AM 3/4/2014 19.5784779 powershell.exe lyncdben01 lyndbaup01.tollgroup.local TCP TCP:Flags=...A...F, SrcPort=60709, DstPort=54994, PayloadLen=0, Seq=2129002479, Ack=1739112270, Win=256 (scale factor 0x8) = 65536 {TCP:75, IPv4:34}
435 10:32:00 AM 3/4/2014 19.6357220 powershell.exe lyndbaup01.group.local lyncdben01 TCP TCP:Flags=...AP...,SrcPort=54994, DstPort=60709, PayloadLen=617, Seq=1739112270 - 1739112887,Ack=2129002479, Win=256 (scale factor 0x8) = 65536 {TCP:75, IPv4:34}
436 10:32:00 AM 3/4/2014 19.6357463 powershell.exe lyncdben01 lyncdbau01.group.local TCP TCP:Flags=...A.R..,SrcPort=60709, DstPort=54994, PayloadLen=0, Seq=2129002480, Ack=1739112887,Win=0 (scale factor 0x8) = 0 {TCP:75,IPv4:34}
问题原因
=========
这个问题实际上是由.Net Framework 3.5 或 .NET Framework 4 的一个已知问题造成的:
https://support.microsoft.com/en-us/kb/2605597/
当使用镜像数据库中连接的重试算法时,数据提供程序将等待一个读(SniReadSync)调用完成。这个调用发送到后端运行SQL Server的服务器,并且等待时间会被计算为连接超时时间乘以0.08 。但是,如果响应慢并且第一次SniReadSync 调用在等待时间过期时未完成,数据提供程序会错误的将连接设置为了doomed
状态。
注意:响应较慢问题在这种情况下可能由与服务端或网络的延迟触发。
解决方案
=========
这个已知问题已在.NET Framework 4.5.2中修复,因此对于.NET Framework 4,可以选择将其升级至4.5.2或更高版本来解决此问题。对于其他版本的. NET Framework,相应的修补程序也已经发布,可以通过安装相应的修补程序解决。详细信息,请参考:https://support.microsoft.com/en-us/kb/2605597/
这就是今天的分享,更多SQL Server案例学习请持续关注本博客的更新。
