【故障公告】SQL语句执行超时引发网站首页访问故障

非常抱歉,今天早上 6:37~8:15 期间,由于获取网站首页博文列表的 SQL 语句出现突发的查询超时问题,造成访问网站首页时出现 500 错误,由此给您带来麻烦,请您谅解。

故障的情况是这样的。

故障期间日志中记录了大量下面的错误。

2020-02-03 06:37:24.635 [Error] An unhandled exception has occurred while executing the request.
/
Microsoft.AspNetCore.Diagnostics.ExceptionHandlerMiddleware
System.Data.SqlClient.SqlException (0x80131904): Timeout expired.  The timeout period elapsed prior to completion of the operation or the server is not responding.
 ---> System.ComponentModel.Win32Exception (258): Unknown error 258
   at System.Data.SqlClient.SqlCommand.<>c.<ExecuteDbDataReaderAsync>b__126_0(Task`1 result)

数据库服务器(阿里云 RDS SQL Server 2016 实例)的 CPU 消耗突增。

数据库服务器的 IOPS 暴增。

通过阿里云 RDS 控制台的 CloudDBA 可以查看到故障期间获取首页博文的 SQL 语句被执行了3万多次,执行这么多次是由于查询超时,无法建立缓存,每次请求都要访问数据库。

发现故障后,我们通过阿里云 RDS 的主备切换恢复了正常。

经过对故障的排查分析,锁定的最大嫌疑对象是 SQL Server 参数嗅探(详见园子里的博文 什么是 SQL Server 参数嗅探)。

对于这种因为重用他人生成的执行计划而导致的水土不服现象,SQL Server 有一个专有名词,叫“参数嗅探 parameter sniffing”。

而且我们找到了引发 SQL Server 参数嗅探问题的条件。

在我们的 open api 中提供了获取首页博文列表的 web api ,但没有限制可以获取的最大博文数,也就是下面的 ItemCount 参数(除了 open api ,其他地方调用时 ItemCount 值都是 20 )。

SELECT TOP (@ItemCount)

假如有人调用 open api 时给 ItemCount 传了一个很大的值,比如 20000 ,虽然调用的是同样的 SQL 语句,但由于 ItemCount 的值不同, SQL Server 可能会生成相差很大的执行计划,对于 ItemCount 20000 性能比较好的执行计划,对于 ItemCount 20 可能性能极差。如果查询 ItemCount 20000 时生成的执行计划被缓存下来,查询 ItemCount 20 时继续使用这个执行计划,就会出现本来好好的 SQL 查询突然变得性能极差。我们今天遇到的故障很可能就是这个原因,而且故障时就一个 SQL 语句出现问题(正好就这个 SQL 查询缓存了水土不服的执行计划),其他都正常,也验证了这个猜测。

通过这次故障,我们吸取的教训是一定要在代码中对 ItemCount 与 PageSize 的最大值进行限制,它不仅仅是带来不必要的低性能查询,而且可能会因为 SQL Server 参数嗅探问题拖垮整个数据库。

原文地址:https://www.cnblogs.com/cmt/p/12255415.html

时间: 2024-10-14 20:20:07

【故障公告】SQL语句执行超时引发网站首页访问故障的相关文章

SQL语句执行顺寻

SQL语句执行的时候是有一定顺序的.理解这个顺序对SQL的使用和学习有很大的帮助. 1.from 先选择一个表,或者说源头,构成一个结果集. 2.where 然后用where对结果集进行筛选.筛选出需要的信息形成新的结果集. 3.group by 对新的结果集分组. 4.having 筛选出想要的分组. 5.select 选择列. 6.order by 当所有的条件都弄完了.最后排序. SQL语句的 执行的顺序就是这样的. SQL语句执行顺寻,布布扣,bubuko.com

统计sql语句执行效率

--统计sql语句执行效率SELECT (total_elapsed_time / execution_count)/1000 N'平均时间ms' ,total_elapsed_time/1000 N'总花费时间ms' ,total_worker_time/1000 N'所用的CPU总时间ms' ,total_physical_reads N'物理读取总次数' ,total_logical_reads/execution_count N'每次逻辑读次数' ,total_logical_reads

mysql优化(三)–explain分析sql语句执行效率

mysql优化(三)–explain分析sql语句执行效率 mushu 发布于 11个月前 (06-04) 分类:Mysql 阅读(651) 评论(0) Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看SQL语句的执行效 果,可以帮助选择更好的索引和优化查询语句,写出更好的优化语句. Explain语法:explain select … from … [where …] 例如:explain select * from

[转] Oracle sql 语句执行过程图文分析

[原文链接]  http://nvd11.blog.163.com/blog/static/200018312201301310585758/ [原文视频]  http://www.jiagulun.com/thread-2674-1-1.html 1. 数据库文件Oracle 数据库文件大概可分为3种,分别是:控制文件(control files): 存放数据库本身物理结构信息数据文件(data files): 存放数据库数据啦~日志文件(log files):  包括重做日志文件和归档日志文

Oracle SQL语句执行完整过程:

SQL语句执行完整过程: 1. 用户进程提交一个sql 语句: update temp set a=a*2,给服务器进程. 2.服务器进程从用户进程把信息接收到后, 在PGA 中就要此进程分配所需内存,存储相关的信息,如在会话内存存储相关的登录信息等. 3.服务 器进程把这个sql  语句的字符转化为ASCII 等效数字码, 接着这个ASCII   码被传递给一个HASH 函数, 并返回一个hash 值,然后服务器进程将到shared pool  中的library cache 中去查找是否存在

oracle学习笔记 SQL语句执行过程剖析讲课

oracle学习笔记 SQL语句执行过程剖析讲课 这节课通过讲述一条SQL语句进入数据库 和其在数据库中的整个的执行过程 把数据库里面的体系结构串一下. 让大家再进一步了解oracle数据库里面的各个进程.存储结构以及内存结构的关联关系. 首先来讲整个体系中有客户端.实例和数据库 数据库里有三类文件 控制文件ctl.数据文件dbf.日志文件log 实例中SGA有六大池子 第一大内存区shared pool即共享池 第二大内存区buffer cache 第三块是redo log 我们主要讲上面的三

SQL语句执行过程详解

一.SQL语句执行原理: 第一步:客户端把语句发给服务器端执行 当我们在客户端执行select语句时, 客户端会把这条SQL语句发送给服务器端,让服务器端的进程来处理这语句.也就是说,Oracle客户端是不会做任何的操作,它的主要任务就是把客户端产生的一些SQL语句发送给服务器端.虽然在客户端也有一个数据库进程,但是,这个进程的作用跟服务器上的进程作用不同.服务器上的数据库进程才会对SQL语句进行相关的处理.不过,有个问题需要说明,就是客户端的进程跟服务器的进程是一 一对应的.也就是说,在客户端

SQL语句执行与结果集的获取

title: SQL语句执行与结果集的获取 tags: [OLEDB, 数据库编程, VC++, 数据库] date: 2018-01-28 09:22:10 categories: windows 数据库编程 keywords: OLEDB, 数据库编程, VC++, 数据库,执行SQL, 获取结果集 --- 上次说到命令对象是用来执行SQL语句的.数据源在执行完SQL语句后会返回一个结果集对象,将SQL执行的结果返回到结果集对象中,应用程序在执行完SQL语句后,解析结果集对象中的结果,得到具

Mysql explain分析sql语句执行效率

mysql优化–explain分析sql语句执行效率 Explain命令在解决数据库性能上是第一推荐使用命令,大部分的性能问题可以通过此命令来简单的解决,Explain可以用来查看SQL语句的执行效 果,可以帮助选择更好的索引和优化查询语句,写出更好的优化语句. Explain语法:explain select - from - [where -] 例如: explain select * from news where id = 1; 输出: id select_type table type