当前位置: 首页 > 科技观察

慢SQL,压垮团队的最后一根稻草!

时间:2023-03-20 02:10:19 科技观察

在实际的业务系统开发中,虽然我们会严格控制代码质量,但是对于慢SQL的检测往往很容易被忽视。今天我们就一起总结一下慢SQL可能带来的系统运行风险。一、什么是慢SQL什么是慢SQL?顾名思义,运行时间较长的SQL语句就是慢SQL!问题是,慢了多久?这种慢其实是一个相对值。在不同的业务场景下,标准要求是不同的。我们都知道,我们每次执行SQL,数据库不仅会返回执行结果,还会返回SQL执行的耗时。以MySQL数据库为例,当我们开启慢SQL监控开关后,在默认配置下,当SQL执行时长超过10秒,就会记录在慢SQL日志文件中。当然这个值也可以重新设置,生产环境中的慢SQL一般设置为0.1~0.2s。当我们设置为0.2s时,当前数据库中所有执行时间超过0.2s的SQL都会被认为是慢SQL。可能有同学会问,为什么要跟踪慢SQL,有什么意义呢?2.慢SQL的危害先说慢SQL的危害。以MySQL数据库为例,可以总结出以下几点:当出现慢查询时,DDL操作会被阻塞,也就是说,建表、修改表、删除表、进行数据备份等操作都需要等待,对于一个实时备份重要数据的系统来说是无法忍受的。慢查询可能会占用mysql大量内存,严重的时候服务器会直接挂掉,整个系统会直接瘫痪。如果慢SQL执行时间过长,可能会导致应用进程超时被kill掉,结果无法返回给客户端。造成数据库幻读和不可重复读的概率更大。假设慢SQL是一个update操作但是因为执行时间长还没有提交,另外一个SQL也在更新数据并且已经提交了。当用户再次查询时,他看到的数据可能与实际结果不符。严重影响用户体验,SQL执行时间越长,页面加载数据的时间越长。以千万级订单表为例,如果不做优化,单表查询10条数据需要39s。首先,先不说可能对数据库服务器造成的潜在压力,没有用户会在页面查询订单查询等39秒!3、如何定位慢SQL说了这么多,我们如何定位慢SQL呢?3.1开启慢SQL监控以MySQL为例,我们可以通过以下方式查询是否开启慢SQL监控。显示像“slow_query_log%”这样的变量;使用以下命令启用慢速SQL监控。执行成功后,客户端需要重新连接才能生效。--开启慢SQL监控setglobalslow_query_log=1;如果要关闭慢速SQL监控,设置为0。--关闭慢速SQL监控setglobalslow_query_log=0;需要注意的是,当服务器重启后,当前配置将失效!3.2配置慢SQL阈值默认慢SQL阈值为10秒,您可以通过以下语句查询慢SQL阈值。--查询慢SQL阈值显示变量,如“long_query_time”;我们可以通过以下方式将慢SQL阈值配置为0.2秒。--修改慢SQL阈值setgloballong_query_time=0.2;然后,退出客户端,重新连接服务器,即可生效!同样,当服务器重启后,当前的配置也会失效!3.3永久启用慢SQL监控以上操作在服务器未重启时一直有效,但当服务器重启后,配置将失效。如果想永久生效,可以通过修改全局配置文件my.cnf使其永久生效。以CentOS为例,打开my.cnf配置文件,添加如下配置变量。[mysqld]slow_query_log=ONslow_query_log_file=/var/lib/mysql/ecs-203056-slow.loglong_query_time=1重启mysql服务器systemctlrestartmysqld3.4慢SQL监控测试初始化一个日志表,数据量10万条左右就够了,然后我们执行SQL,看看是否正常捕获。很明显,慢SQL已经被捕获并记录下来了。日志内容详解:时间:表示客户端的查询时间。root[root]:表示客户端查询用户和IP。Query_time:表示查询时间。Lock_time:表锁等待时间。注意这里不会体现InnoDB的行锁等待。Rows_sent:表示返回多少行记录(结果集)。Rows_examined:表示已经检查了多少条记录。另外,我们还可以使用mysqldumpslow命令工具来分析慢SQL的数据情况,可以通过以下参数进行组合分析-s表示排序方式,支持的参数如下al:平均锁定时间ar:averagereturnrecordsnumberat:平均查询时间c:访问次数l:锁定时间r:返回记录t:查询时间-tNUM返回之前的数据条数-gPATTERN后面是正则匹配模式,不区分大小写常见用法如下:查询返回记录集最多的10条SQL;mysqldumpslow-sr-t10/var/lib/mysql/ecs-203056-slow.log查询访问次数最多的10条SQL;mysqldumpslow-sc-t10/var/lib/mysql/ecs-203056-slow.log查询包含按时间排序的前10个条目中的左连接查询语句。mysqldumpslow-st-t10-g"LEFTJOIN"/var/lib/mysql/ecs-203056-slow.log4.慢SQL是如何产生的?面对如此耗时的SQL,我们不禁发出一个Question,它是怎么发生的呢?它从SQL的执行过程说起。我们简单看一下下图。一条SQL语句在执行时,大致可以分为以下几个步骤:如果开启了查询缓存,则优先查询缓存,如果命中则直接将结果返回给客户端。如果缓存未命中,此时MySQL需要弄清楚这条语句需要做什么,然后通过分析器进行词法分析和语法分析。MySQL在搞清楚要做什么之后,会通过优化器对SQL进行优化,生成一个最优的执行计划。最后,执行器与存储引擎提供的接口进行交互,并将结果返回给客户端。在MySQL执行过程中,优化器可能会修改我们即将执行的SQL。改造思路是:根据查找条件找出SQL中所有可能的索引。然后计算全表扫描的成本开销。然后计算使用不同索引执行查询的成本开销。最后会比较各种执行计划的成本,找出成本最小的那个。其中,成本开销值的计算主要包括I/O成本和CPU成本两个指标。从I/O成本的角度看:表的数据量越大,需要的I/O次数就越多。I/O从磁盘读取数据比从缓存读取数据需要更多时间。全表扫描比通过索引快速查找消耗更多的时间和I/O次数。从CPU成本来看:当SQL中有排序、子查询等复杂操作时,CPU需要先将数据存储到临时表中,然后再对数据进行处理,需要更多的CPU资源。全表扫描也比通过索引快速查找需要更多的CPU资源。因此不难发现,在不启用缓存的情况下,当表数据量较大时,如果SQL不使用索引,很容易出现查询慢的问题。5.总结本文主要针对慢SQL的定位和可能存在的风险进行阐述。整个介绍算是入门级的知识。文章内容难免有些地方理解的不够透彻。欢迎网友们留言指出!限于篇幅,我们将在下一篇文章介绍慢SQL的优化思路。6.参考1.稀土掘金-三只猪皮匠-慢SQL优化的一点想法2.博客园-雪山上的蒲公英-慢SQL分析3.博客园-慢查询的危害