且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

【巡检问题分析与***实践】RDS MySQL慢SQL问题

更新时间:2022-05-25 03:00:43

前言

判断查询的性能就是看查询执行的时间,这个时间针对不同的业务要求上也有差异。在同一时间内SQL执行的越快,执行的SQL就越多,完成的业务逻辑就越多。同样一个业务场景不同的架构设计、数据库表索引设计,由不同的人来做效果是不同的,有的人可以用很低的成本,RDS规格,ECS规格跑出很高的性能。***的情况是自顶向下了解业务,以及每个业务涉及的SQL,这样就能厘清业务和数据库负载的关系;也能找到短板,并对短板做有针对性的优化;全链路压测就是做的这个事情。另外也可以借鉴xtrace,strace等理念在分布式环境中做全链路的监控,阿里云已经有这样的产品叫链路追踪,可以清楚地监控从应用组件到基础组件,哪一个环节耗时最长,哪一个环节报错,详细请参考文档 https://www.aliyun.com/product/xtrace 。全链路监控和全链路压测是值得大多数系统学习的。

下面针对数据库的各种导致SQL慢的排查思路,原因和解决方法进行阐述:

实例达到瓶颈

如果监控比较细微或对响应时间比较敏感的话,瓶颈很容易被监控到,达到瓶颈时一般可能有以下几种因素:

  1. 随着业务的增长而没有扩容,总有那么一天系统变慢;
  2. 随着时间的变化,大量的磁盘擦写或快过保的机器性能有损耗,也会达到瓶颈;
  3. 随着时间的累计,数据只增加不清理,表的大小也不断增加,有可能原来不慢的SQL变慢,如:索引缺失;可以借助自治服务诊断。

控制台路径是选择“云数据库RDS”->选择“实例列表”->点击实例链接,进入实例页面->选择“自治服务”->选择“资源监控”,详细参考 https://help.aliyun.com/document_detail/95667.html 。如果资源使用利用率各项指标都100%,可能是实例达到了瓶颈,这时候建议升级实例规格,方法参考 https://help.aliyun.com/document_detail/96061.html

判断实例有没有达到瓶颈,比较好的方法是先找到实例的性能基准值,先用sysbench或其他测试工具构建基准测试,当不管怎么增加压力,数据库的性能再也上不去时说明基准值已经出来了,在复杂场景下的QPS/TPS响应时间很少会超过基准值的。

版本升降级

数据库的版本升级可能会导致SQL执行计划发生改变,执行计划查询类型依次从好到坏的顺序是“system > const > eq_ref > ref > fulltext > ref_or_null > index_merge > unique_subquery > index_subquery > range > index > all”(官方链接 https://dev.mysql.com/doc/refman/5.6/en/explain-output.html#explain-join-types ),查询类型从“range -> index”,因为SQL的请求变慢,业务又不断重试请求,导致SQL并行查询比较多,进而影响应用线程释放慢,导致应用连接池耗尽,影响整个业务。查看近期有没有修改过参数的控制台路径是选择“云数据库RDS”->选择“历史事件”,详细参考 https://help.aliyun.com/document_detail/131008.html ,如下图所示:

【巡检问题分析与***实践】RDS MySQL慢SQL问题

参数调整

参数buffer_pool_instances/join_buffer_size/AHI等的变化也会导致性能变慢。关于这方面的文章比较多,这里不一一赘述。查看近期有没有修改过参数的控制台路径是选择“云数据库RDS”->选择“实例列表”->点击实例链接,进入实例页面->选择“参数设置”->选择“修改历史”,详细参考 https://help.aliyun.com/document_detail/131008.html ,如下图所示:

【巡检问题分析与***实践】RDS MySQL慢SQL问题

缓存失效

缓存的设计在架构上很好地承担了大量的查询,但并不能保证缓存命中率100%,如果缓存失效,也会有大量的查询涌到数据库端,导致性能下降。从数据库表现来说,看到各方面的资源(通常是CPU)打满,QPS/活跃线程飙的非常高。这样的情况RDS MySQL可以用SQL限流、打开线程池、语句并行队列、Fast Query Cache等可以缓解,详情参考https://help.aliyun.com/document_detail/130306.html 。目前数据库自治服务DAS,可以提供自动调参/自动扩容/SQL自动优化/SQL自动限流的工作,详情参考 https://help.aliyun.com/document_detail/164859.html

批量操作

如果有大批量的数据导入、删除、或拖数据的情况。

批量数据导入 

这种情况可以从磁盘空间,或SQL洞察/慢查询里找到对应语句。如从binlog的大小,正常情况每个binlog问卷大小是500MB,如果有超过500MB的,就可以看是否有异常情况。

【巡检问题分析与***实践】RDS MySQL慢SQL问题

也可以从监控上看哪部分的空间有变化。

【巡检问题分析与***实践】RDS MySQL慢SQL问题

如果有批量数据导入IOPS上也会增加。【巡检问题分析与***实践】RDS MySQL慢SQL问题

事务数也会增加。

【巡检问题分析与***实践】RDS MySQL慢SQL问题

InnoDB的写入量也会增加。

【巡检问题分析与***实践】RDS MySQL慢SQL问题

日志文件的写入也会增加。

【巡检问题分析与***实践】RDS MySQL慢SQL问题

InnoDB层的写入也会增加。

【巡检问题分析与***实践】RDS MySQL慢SQL问题

批量数据删除/回收

这种情况可以从磁盘空间,或SQL洞察/慢查询里找到对应语句。

【巡检问题分析与***实践】RDS MySQL慢SQL问题

【巡检问题分析与***实践】RDS MySQL慢SQL问题

【巡检问题分析与***实践】RDS MySQL慢SQL问题

可以看到truncate table时select 1都很慢。


【巡检问题分析与***实践】RDS MySQL慢SQL问题

拖数据

这种情况可以通过监控指标的变化或SQL洞察/慢查询里找到对应语句。

【巡检问题分析与***实践】RDS MySQL慢SQL问题

【巡检问题分析与***实践】RDS MySQL慢SQL问题

未关闭的事务

如果某个任务突然变慢,应该考虑是否有锁阻塞的问题。可以通过“如何定位长时间未关闭的事务和处理方法”这篇文章找到未释放的锁,应通过更快地释放锁来改善。如下图CPU和IOPS的利用率并不高,但应用拥堵,MySQL的活跃会话上涨就是存在未关闭的事务导致的。

【巡检问题分析与***实践】RDS MySQL慢SQL问题


未提交事务:

【巡检问题分析与***实践】RDS MySQL慢SQL问题

定时任务

如果负载随时间有规律性变化,则瓶颈随负载有规律性地变化,很大可能是定时任务引起的,如图所示:

【巡检问题分析与***实践】RDS MySQL慢SQL问题

SQL异常

查询慢有很多种原因导致,这种情况可能是由于库表结构设计不合理,或索引缺失,或扫描行数太多,或不常用到的查询条件导致,这种情况需要开发人员修改。

影响SQL语句执行的因素大概分为以下几类:表有哪些索引、存储特性、数据库引擎特性、查询条件的区分度、结果集大小、表的数据量、CPU时间。关于这一点已经讲的比较多,详细可以参考阿里云数据库***实践 https://yq.aliyun.com/live/1938

此外还可以使用数据库自治服务优化慢SQL,可参考https://help.aliyun.com/document_detail/167895.html

业务场景发生改变

如何确定业务场景发生了改变呢?有两种可能:

1. 应用进行过发布 

应用有没有进行过发布,需要看下应用的部署日志或发布系统可以查到痕迹。

2. 没发布,功能早上线,但不经常用,某天用户点了某个功能。

如果想确切定位同时段的SQL是否一样,就需要打开审计日志。打开审计日志的方法参考文档 https://help.aliyun.com/document_detail/96123.html 。同时段的SQL可以跟昨天同时间对比,或上周同时间对比。借助SQL洞察的SQL分析功能,或者更方便地用DAS专业版的“SQL对比”/“来源统计”。发现和没有问题时间段的SQL,找到来源即可。

【巡检问题分析与***实践】RDS MySQL慢SQL问题

或用DAS数据库自治服务的"一键诊断",路径参考https://help.aliyun.com/document_detail/99478.html

【巡检问题分析与***实践】RDS MySQL慢SQL问题

扫描行数多

路径地址:阿里云控制台->选择对应数据库引擎->找到对应实例,点击“实例ID/名称”->选择“SQL洞察”或“自治服务”里的“慢SQL”

【巡检问题分析与***实践】RDS MySQL慢SQL问题

多表join

这种情况可以通过监控指标的变化或SQL洞察/慢查询里找到对应语句。

【巡检问题分析与***实践】RDS MySQL慢SQL问题

索引不合理

例如:

【巡检问题分析与***实践】RDS MySQL慢SQL问题

全表扫描

全表扫描一般发生在索引不合理或没有WHERE条件的SQL语句中,索引不合理好解决建立合适的索引就可以了,但对于没有WHERE条件的SQL语句发生时可以kill或降级业务解决。没有WHERE条件但SQL语句是高风险SQL,建议分批执行或放在业务低峰期执行,当然了尽量带上WHERE条件。如下图就是不带WHERE条件的,在DAS控制台/慢查询/SQL洞察等都可以找到。

【巡检问题分析与***实践】RDS MySQL慢SQL问题

CPU达到瓶颈

CPU在系统中相当于大脑,当CPU达到瓶颈后调度IO等就慢,也会导致慢SQL产生,这种情况可以从监控指标上看出。如

【巡检问题分析与***实践】RDS MySQL慢SQL问题

IO慢

IOPS达到瓶颈 

如果慢SQL里出现DML,很大程度是IOPS利用率较高,如:

【巡检问题分析与***实践】RDS MySQL慢SQL问题

可以从SQL洞察里找到慢SQL:

【巡检问题分析与***实践】RDS MySQL慢SQL问题

也可从慢日志明细看到:

【巡检问题分析与***实践】RDS MySQL慢SQL问题【巡检问题分析与***实践】RDS MySQL慢SQL问题

刷脏导致的IO慢

MySQL触发刷脏的时机有:RedoLog满,内存不够用,内存刷脏过程中的额外开销。这种情况可能会触发Buffer Pool的锁

【巡检问题分析与***实践】RDS MySQL慢SQL问题

业务场景发生变化

业务进行过发布,或有不经常访问的业务突发访问比如ad-hoc类等,从监控指标上可以看到异常。

【巡检问题分析与***实践】RDS MySQL慢SQL问题

总结

哪些可以帮助我们定位慢SQL?

  • 监控指标

对比两个时间段的监控指标的差异,如资源层面的差异,引擎层面的差异,选择“云数据库RDS”->选择“实例列表”->点击实例链接,进入实例页面->选择“监控与报警”->选择“资源监控”/“引擎监控”,下面看下各个指标的含义:

监控项

含义

说明

磁盘空间

实例的磁盘空间占用历史趋势,单位GB

IOPS

RDS实例的IOPS(每秒IO请求次数)

连接数

当前总连接数

CPU使用率

RDS实例CPU使用率(占操作系统总数)

网络流量

MySQL实例平均每秒钟的输入、输出流量,单位为KB

QPS/TPS

每秒钟SQL语句执行次数和事务处理数

InnoDB缓存读命中率、使用率、脏块率

InnoDB缓冲池的读命中率、使用率以及缓冲池脏块的百分率

InnoDB读写量

InnoDB平均每秒读取和写入的数据量

InnoDB读写次数

InnoDB每秒钟的读取和写入的次数

InnoDB日志

InnoDB的日志写入情况

MySQL执行语句时在硬盘上自动创建的临时表的数量

执行语句时在硬盘上自动创建的临时表的数量

MyISAM Key Buffer

MyISAM平均每秒的Key Buffer使用状况

MyISAM读写次数

MyISAM平均每秒的读写次数

MySQL_COMDML

数据库每秒SQL语句执行次数,包括的类型如下:Insert、Delete、Insert_Select、Replace、Replace_Select、Select、Update

MySQL_RowDML

InnoDB每秒钟操作执行次数,包括:

  • 每秒向日志文件的物理写次数
  • 每秒从 InnoDB 表读取、更新、删除、插入的行数

  • 慢日志
  • SQL洞察
  • 数据库自治服务

因为上面已经有路径或帮助文档,这里不再赘述。在实际业务场景中情况可能会比上面提到的情况复杂的多,有可能是多种情况的叠加,不过排查问题的思路是一致的,希望上述方法对您有帮助。