SQL语句执行超时引发网站首页访问故障问题
非常抱歉,今天早上6:37~8:15期间,由于获取网站首页博文列表的SQL语句出现突发的查询超时问题,造成访问网站首页时出现500错误,由此给您带来麻烦,请您谅解。
故障的情况是这样的。
故障期间日志中记录了大量下面的错误。
2020-02-0306:37:24.635[Error]Anunhandledexceptionhasoccurredwhileexecutingtherequest./Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddlewareSystem.Data.SqlClient.SqlException(0x80131904):Timeoutexpired.Thetimeoutperiodelapsedpriortocompletionoftheoperationortheserverisnotresponding.--->System.ComponentModel.Win32Exception(258):Unknownerror258atSystem.Data.SqlClient.SqlCommand.<>c.
b__126_0(Task`1result)
数据库服务器(阿里云RDSSQLServer2016实例)的CPU消耗突增。
数据库服务器的IOPS暴增。
通过阿里云RDS控制台的CloudDBA可以查看到故障期间获取首页博文的SQL语句被执行了3万多次,执行这么多次是由于查询超时,无法建立缓存,每次请求都要访问数据库。
发现故障后,我们通过阿里云RDS的主备切换恢复了正常。
经过对故障的排查分析,锁定的最大嫌疑对象是SQLServer参数嗅探(详见园子里的博文什么是SQLServer参数嗅探)。
对于这种因为重用他人生成的执行计划而导致的水土不服现象,SQLServer有一个专有名词,叫“参数嗅探parametersniffing”。
而且我们找到了引发SQLServer参数嗅探问题的条件。
在我们的openapi中提供了获取首页博文列表的webapi,但没有限制可以获取的最大博文数,也就是下面的ItemCount参数(除了openapi,其他地方调用时ItemCount值都是20)。
SELECTTOP(@ItemCount)
假如有人调用openapi时给ItemCount传了一个很大的值,比如20000,虽然调用的是同样的SQL语句,但由于ItemCount的值不同,SQLServer可能会生成相差很大的执行计划,对于ItemCount20000性能比较好的执行计划,对于ItemCount20可能性能极差。如果查询ItemCount20000时生成的执行计划被缓存下来,查询ItemCount20时继续使用这个执行计划,就会出现本来好好的SQL查询突然变得性能极差。我们今天遇到的故障很可能就是这个原因,而且故障时就一个SQL语句出现问题(正好就这个SQL查询缓存了水土不服的执行计划),其他都正常,也验证了这个猜测。
通过这次故障,我们吸取的教训是一定要在代码中对ItemCount与PageSize的最大值进行限制,它不仅仅是带来不必要的低性能查询,而且可能会因为SQLServer参数嗅探问题拖垮整个数据库。
总结
以上所述是小编给大家介绍的SQL语句执行超时引发网站首页访问故障问题,希望对大家有所帮助!
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。