网站故障公告3:应该找到了问题的真正原因
2013-04-17 01:41
363 查看
根据故障期间的错误信息:
Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
找到了这三篇博文:
1. ADO.NET application connecting to a mirrored SQL Server Database may timeout long before the actual connection timeout elapses, sometimes within milliseconds
2. Interesting SQL Server Mirroring Problem
3. You may see an instant timeout when connecting to a SQL Server Mirrored database from a .Net application
谈到的都是SQL Server数据库镜像引起的"Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding." 尤其是第3篇中的一段文字:
As per the Connection Retry Algorithm for Mirroring, SqlClient code takes the connection timeout and multiplies it by 0.08 to determine the milliseconds to wait for first read (SniReadSync call). Now if this first SniReadSync fails due to a timeout (due to a slow response from the server), the connection is incorrectly set to a doomed state by the sqlClient .NET Provider and this causes the connection attempt to prematurely fail before the entire connection timeout expires.
联想到阿里云RDS与我们之前自己的物理服务器、阿里云云服务器时最大的不同之处是:阿里云RDS使用了SQL Server数据库镜像。
立即眼前一亮!问题的真正原因就在这——ADO.NET对SQL Server数据库镜像处理上的bug。
故障是这么发生的:
1. 我们在博客程序的连接字符串中设置的是Connect Timeout=30(默认是15);
2. SqlClient将 30(Connect Timeout) × 0.08 = 2.4s 作为超时时间发起一次数据库连接操作;
3. 对于SQL Server数据库镜像的场景,SqlClient只对Principal数据库发起1次且仅此1次数据库连接操作(不合理,至少失败时重试一次);
4. 如果超时,SqlClient就会去连接“连接字符串”中通过Failover Partner指定的镜像数据库;(4月17日故障时就是发生了超时情况)
5. 而我们在连接字符串中没有指定Failover Partner,SqlClient也没有镜像数据库可连,于是SqlClient就自以为是地Timeout。
这是ADO.NET的一个bug,微软在2011年就确认了这个bug,说是在下一版本中(也就是现在的.NET Framework 4.5)会修复这个问题。
Microsoft has confirmed that this is a problem in the current release of ADO.NET. This issue will be fixed in ADO.NET version, ships with Visual Studio 2011.
而我们的博客程序用的是.NET Framework 4.0,没能躲开这个bug的魔爪。
目前还不知道.NET Framework 4.5是不是真的解决了这个问题。
真没想到,最终竟然是被微软坑的!
临时解决方法:在连接字符串中设置Connect Timeout=150,并从网络与数据库层面尽量减少连接时间。
补充:有人在阿里云论坛上提到“之前用RDS时就会偶尔出现秒级以上的延时”,这可能也是一个肇事者。
更新:“问题的真正原因”背后的真正问题是为什么数据库连接会超时(注:只是连接,查询还没开始)?
相关博文:
网站故障公告1:使用阿里云RDS之后一个让人欲哭无泪的下午
网站故障公告2:找到问题的重要线索
Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
找到了这三篇博文:
1. ADO.NET application connecting to a mirrored SQL Server Database may timeout long before the actual connection timeout elapses, sometimes within milliseconds
2. Interesting SQL Server Mirroring Problem
3. You may see an instant timeout when connecting to a SQL Server Mirrored database from a .Net application
谈到的都是SQL Server数据库镜像引起的"Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding." 尤其是第3篇中的一段文字:
As per the Connection Retry Algorithm for Mirroring, SqlClient code takes the connection timeout and multiplies it by 0.08 to determine the milliseconds to wait for first read (SniReadSync call). Now if this first SniReadSync fails due to a timeout (due to a slow response from the server), the connection is incorrectly set to a doomed state by the sqlClient .NET Provider and this causes the connection attempt to prematurely fail before the entire connection timeout expires.
联想到阿里云RDS与我们之前自己的物理服务器、阿里云云服务器时最大的不同之处是:阿里云RDS使用了SQL Server数据库镜像。
立即眼前一亮!问题的真正原因就在这——ADO.NET对SQL Server数据库镜像处理上的bug。
故障是这么发生的:
1. 我们在博客程序的连接字符串中设置的是Connect Timeout=30(默认是15);
2. SqlClient将 30(Connect Timeout) × 0.08 = 2.4s 作为超时时间发起一次数据库连接操作;
3. 对于SQL Server数据库镜像的场景,SqlClient只对Principal数据库发起1次且仅此1次数据库连接操作(不合理,至少失败时重试一次);
4. 如果超时,SqlClient就会去连接“连接字符串”中通过Failover Partner指定的镜像数据库;(4月17日故障时就是发生了超时情况)
5. 而我们在连接字符串中没有指定Failover Partner,SqlClient也没有镜像数据库可连,于是SqlClient就自以为是地Timeout。
这是ADO.NET的一个bug,微软在2011年就确认了这个bug,说是在下一版本中(也就是现在的.NET Framework 4.5)会修复这个问题。
Microsoft has confirmed that this is a problem in the current release of ADO.NET. This issue will be fixed in ADO.NET version, ships with Visual Studio 2011.
而我们的博客程序用的是.NET Framework 4.0,没能躲开这个bug的魔爪。
目前还不知道.NET Framework 4.5是不是真的解决了这个问题。
真没想到,最终竟然是被微软坑的!
临时解决方法:在连接字符串中设置Connect Timeout=150,并从网络与数据库层面尽量减少连接时间。
补充:有人在阿里云论坛上提到“之前用RDS时就会偶尔出现秒级以上的延时”,这可能也是一个肇事者。
更新:“问题的真正原因”背后的真正问题是为什么数据库连接会超时(注:只是连接,查询还没开始)?
相关博文:
网站故障公告1:使用阿里云RDS之后一个让人欲哭无泪的下午
网站故障公告2:找到问题的重要线索
相关文章推荐
- 应该找到了问题的真正原因
- 找到问题的真正原因:20121021服务器故障处理经历
- 找到问题的真正原因:20121021服务器故障处理经历
- 网站故障公告2:找到问题的重要线索
- Win7系统经常弹出“Windows检测到一个硬盘问题”提示窗口的故障原因及解决方法
- eclipse中某工程的断点进不去问题,折腾了N个小时才找到原因,郁闷
- 谈web2.0网站初期规划应该考虑的问题[转载]
- [网站公告]又拍云API故障造成图片无法上传(已恢复)
- 未能找到类型或命名空间名称"xxxxxx"的真正原因
- 大型网站都喜欢把js写在html中的真正原因
- WAP通讯故障的问题找到了,但还是郁闷
- 关于asp.net 发布网站的问题 郁闷的未能找到文件
- VS2003升级到2005后使用AjaxControlToolkit的一诡异问题(已找到解决办法,求解原因)
- asp.net 未能找到文件“c:\windows\system32\inetsrv\02100.text”。 网站经常遇到这样的问题求解
- thinkphp网站支付宝异步回调验签失败问题,发现一个原因点
- Tomcat部署servlet小应用无法找到相应的servlet类的问题可能原因
- 网站服务器应该注意的问题
- [网站公告]18:07-18:20阿里云SLB故障造成网站不能正常访问
- 关于网站建设中应该注意的若干问题(一):微信