【笔记】最佳实践—如何限流慢SQL

简介: 本文介绍了如何对慢SQL进行有效限流。

在数据库会话或者慢日志中发现大量慢SQL,大量占用数据库资源,同时活跃会话数、CPU使用率、IOPS、内存使用率等监控指标一项或者多项处于高位。分析后发现这些慢SQL不属于核心业务,是优化不足的烂SQL,为保障核心业务的稳定运行,此时我们需要对其进行限流。

相关限流语法,请参见SQL限流

SQL限流的运维操作步骤

  1. 实例会话页面或使用如下语句发现慢SQL。
select *

from information_schema.processlist
where COMMAND!= 'SLEEP'
and TIME>= 1000
order by TIME DESC;
  1. 分析慢SQL,请参见如何分析及优化慢SQL
  2. 创建限流规则,可使用SQL命令,或者实例会话里SQL限流功能上的白屏化操作。
  3. 从以下几方面观察限流规则效果。
    • 监控指标恢复情况;
    • 业务侧反馈;
    • show ccl_rules查看每个限流规则的限流情况的统计信息;
    • 查看会话和SQL日志。
  1. 创建索引、修改SQL、增加资源等。
  2. 关闭限流规则,使用DROP CCL_RULE或者CLEAR CCL_RULES语句。

如下案例说明了如何对发现的慢SQL进行限流,您可以参照案例中的限流规则,修改后使用。

案例1: 慢SQL属于同一个SQL模版

某DBA收到了数据库资源某指标处于高位的报警,查看数据库慢日志和会话后均发现有如下的慢SQL:


+--------+---------------+---------------------+--------------------+---------+------+-------+----------------------------------------------+-----------------+
| ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO | SQL_TEMPLATE_ID |
+--------+---------------+---------------------+--------------------+---------+------+-------+----------------------------------------------+-----------------+
| 951494 | userxxxxxxxxx | 222.0.0.1:33830 | analy_db | Query | 40 | | select * from bmsql_oorder where `o_id` > 12 | 65c92c88 |
| 952468 | userxxxxxxxxx | 222.0.0.1:33517 | analy_db | Query | 43 | | select * from bmsql_oorder where `o_id` > 10 | 65c92c88 |
| 953468 | userxxxxxxxxx | 222.0.0.1:33527 | analy_db | Query | 43 | | select * from bmsql_oorder where `o_id` > 23 | 65c92c88 |
| 954468 | userxxxxxxxxx | 222.0.0.1:33537 | analy_db | Query | 43 | | select * from bmsql_oorder where `o_id` > 25 | 65c92c88 |
| 955468 | userxxxxxxxxx | 222.0.0.1:33547 | analy_db | Query | 43 | | select * from bmsql_oorder where `o_id` > 27 | 65c92c88 |
+--------+---------------+---------------------+--------------------+---------+------+-------+----------------------------------------------+-----------------+

可见,这些慢SQL属于同一个SQL模版(模版ID为65c92c88):


select * from bmsql_oorder where `o_id` > ?

bmsql_oorder为一个数据量较大的表,而且列o_id上没有索引,显然这个一个未经优化的SQL,占尽了数据库资源影响了其他重要SQL的正常执行。这是一个非常适合利用模版ID去做SQL限流的场景。

创建限流规则

  • 如果这个SQL模版的SQL不应该在当时执行,而且应该在业务低峰期执行,则我们可以创建SQL限流规则不让它执行:
CREATE CCL_RULE `KILL_CCL`       //限流规则名称为KILL_CCL
ON `analy_db`.`*` //&匹配analy_db下的所有表上执行的SQL
TO 'userxxxxxxxxx'@'%' //&匹配来自userxxxxxxxxx用户的SQL
FOR SELECT //&匹配是SELECT类型的SQL语句
FILTER BY TEMPLATE '65c92c88' //&匹配模版ID
WITH MAX_CONCURRENCY = 0; //设置单节点并发度为0,不允许匹配到的SQL执行
  • 客户端再次执行这类SQL的时候将会返回报错信息:
ERROR 3009 (HY000): 13172dbaf2801000[analy_db]Exceeding the max concurrency 0 per node of ccl rule KILL_CCL
  • 如果允许这个SQL模版的SQL少量执行,只要不占尽数据库资源就行,则我们可以在创建限流规则的时候设置一定的并发度:
CREATE CCL_RULE `KILL_CCL_2`       //限流规则名称为KILL_CCL
ON `analy_db`.`*` //&匹配analy_db下的所有表上执行的SQL
TO 'userxxxxxxxxx'@'%' //&匹配来自userxxxxxxxxx用户的SQL
FOR SELECT //&匹配是SELECT类型的SQL语句
FILTER BY TEMPLATE '65c92c88' //&匹配模版ID 65c92c88
WITH MAX_CONCURRENCY = 2; //允许单个节点可以同时有两个这样的SQL在执行
  • 也可使用实例会话页面里的SQL限流功能,进行如下操作:8..png
  • 如果希望这个SQL模版的SQL执行的时候可以慢,但尽量不要出错,则可以设置等待队列和等待超时时间(默认为600秒):


CREATE CCL_RULE `QUEUE_CCL_2`       //限流规则名称为KILL_CCL
ON `analy_db`.`*` //&匹配analy_db下的所有表上执行的SQL
TO 'userxxxxxxxxx'@'%' //&匹配来自userxxxxxxxxx用户的SQL
FOR SELECT //&匹配是SELECT类型的SQL语句
FILTER BY TEMPLATE '65c92c88' //&匹配模版ID
WITH MAX_CONCURRENCY = 2, WAIT_QUQUE_SIZE=20, WAIT_TIMEOUT=500; //单节点并发度为2,单节点等待队列长度为20,等待超时时间为500秒

创建完后,可以通过show ccl_rules指令查询各个限流规则的实际效果,比如当前匹配到某个限流规则的正在执行的SQL的数量、被限流报错的SQL数量、总匹配成功次数等。如果想放开被限流SQL,比如在增加了某个索引后,被限流SQL的执行效率变高了,则可以通过drop ccl_rule命令来关闭指定限流规则,或者使用clear ccl_rules来关闭所有的限流规则。

当然上面的SQL也可以通过关键字来限流,将SQL语句上的关键字做拆分,我们得到关键字列表:

  • select
  • from
  • bmsql_oorder
  • where
  • `o_id`

创建限流规则:


CREATE CCL_RULE `KILL_CCL`       //限流规则名称为KILL_CCL
ON `analy_db`.`*` //&匹配analy_db下的所有表上执行的SQL
TO 'userxxxxxxxxx'@'%' //&匹配来自userxxxxxxxxx用户的SQL
FOR SELECT //&匹配是SELECT类型的SQL语句
FILTER BY KEYWORD('select','from','bmsql_oorder','where','`o_id`') //&匹配模版ID
WITH MAX_CONCURRENCY = 0; //设置单节点并发度为0,不允许匹配到的SQL执行

在能获取到模版ID(在SQL日志、explain命令、会话中)的情况下,我们还推荐使用更精准的基于模版ID的限流。

也可使用实例会话页面里的SQL限流功能,操作如下:

案例2: 慢SQL都是同一个SQL

某DBA收到了数据库资源某指标处于高位的报警,查看数据库慢日志和会话后均发现有如下的慢SQL:


+--------+---------------+---------------------+--------------------+---------+------+-------+---------------------------------------------------+-----------------+
| ID     | USER          | HOST                | DB                 | COMMAND | TIME | STATE | INFO                                              | SQL_TEMPLATE_ID |
+--------+---------------+---------------------+--------------------+---------+------+-------+---------------------------------------------------+-----------------+
| 951494 | userxxxxxxxxx | 222.0.0.1:33830     | analy_db           | Query   |   40 |       | select * from bmsql_oorder where o_carrier_id = 2 | 438b00e4        |
| 952468 | userxxxxxxxxx | 222.0.0.1:33517     | analy_db           | Query   |   43 |       | select * from bmsql_oorder where o_carrier_id = 2 | 438b00e4        |
| 953468 | userxxxxxxxxx | 222.0.0.1:33527     | analy_db           | Query   |   43 |       | select * from bmsql_oorder where o_carrier_id = 2 | 438b00e4        |
| 954468 | userxxxxxxxxx | 222.0.0.1:33537     | analy_db           | Query   |   43 |       | select * from bmsql_oorder where o_carrier_id = 2 | 438b00e4        |
| 955468 | userxxxxxxxxx | 222.0.0.1:33547     | analy_db           | Query   |   43 |       | select * from bmsql_oorder where o_carrier_id = 2 | 438b00e4        |
+--------+---------------+---------------------+--------------------+---------+------+-------+---------------------------------------------------+-----------------+

bmsql_oorder中的符合o_carrier_id = 2条件的有较多记录,导致了慢SQL,如果使用模版ID限流,则会影响o_carrier_id不是2的SQL语句,如果使用关键字限流则会影响类似如下的正常SQL:


select * from bmsql_oorder where o_carrier_id = 2 limit 1;

select * from bmsql_oorder where o_carrier_id = 2 and o_c_id = 1;

限流具体的SQL,可以使用模版ID加关键字的方法,创建如下限流规则:


CREATE CCL_RULE `KILL_CCL`       //限流规则名称为KILL_CCL
ON `analy_db`.`*` //&匹配analy_db下的所有表上执行的SQL
TO 'userxxxxxxxxx'@'%' //&匹配来自userxxxxxxxxx用户的SQL
FOR SELECT //&匹配是SELECT类型的SQL语句
FILTER BY TEMPLATE '438b00e4' //&匹配模版ID 438b00e4
FILTER BY KEYWORD('o_carrier_id','2') //&匹配参数关键字
WITH MAX_CONCURRENCY = 0; //设置单节点并发度为0,不允许匹配到的SQL执行

如果使用PolarDB-X的CN内核版本为5.4.11以上,且该SQL不在prepare模式下执行,还可以使用如下高阶语法进行限流:


CREATE CCL_RULE `KILL_CCL`       //限流规则名称为KILL_CCL
ON `analy_db`.`*` //&匹配analy_db下的所有表上执行的SQL
TO 'userxxxxxxxxx'@'%' //&匹配来自userxxxxxxxxx用户的SQL
FOR SELECT //&匹配是SELECT类型的SQL语句
FILTER BY QUERY 'select * from bmsql_oorder where o_carrier_id = 2' //&匹配SQL语句
WITH MAX_CONCURRENCY = 0; //设置单节点并发度为0,不允许匹配到的SQL执行

案例3: 慢SQL集包含多个SQL模版

某DBA收到了数据库资源某指标处于高位的报警,查看数据库慢日志和会话后均发现有如下的慢SQL:


+--------+---------------+---------------------+--------------------+---------+------+-------+---------------------------------------------------+-----------------+
| ID | USER | HOST | DB | COMMAND | TIME | STATE | INFO | SQL_TEMPLATE_ID |
+--------+---------------+---------------------+--------------------+---------+------+-------+---------------------------------------------------+-----------------+
| 951494 | userxxxxxxxxx | 222.0.0.1:33830 | analy_db | Query | 40 | | select * from bmsql_oorder where o_carrier_id = 2 | 438b00e4 |
| 952468 | userxxxxxxxxx | 222.0.0.1:33517 | analy_db | Query | 43 | | select * from bmsql_order_line where ol_o_id = 2 | 57a572f9 |
| 953468 | userxxxxxxxxx | 222.0.0.1:33527 | analy_db | Query | 43 | | select * from bmsql_new_order where no_w_id = 2 | de6eefdb |
+--------+---------------+---------------------+--------------------+---------+------+-------+---------------------------------------------------+-----------------+

此种情况较为复杂,如果一条明显执行效率很高的SQL也成了慢SQL,则不排除是由于网络抖动或者服务节点异常等原因导致运行效率降低从而产生大批量的慢SQL,也可能是由于真正的烂SQL完全耗尽了资源,导致原本正常的SQL也成了慢SQL,需要通过SQL分析具体原因,不在本文的讨论范围内。假设已经确定了需要限流的慢SQL,我们则可以针对每个模版ID创建一个限流规则。但随着限流规则增加,匹配效率会略有降低,当PolarDB-X的CN内核版本为5.4.11以上时,我们推荐使用多模版限流:


CREATE CCL_RULE `KILL_CCL`       //限流规则名称为KILL_CCL
ON `analy_db`.`*` //&匹配analy_db下的所有表上执行的SQL
TO 'userxxxxxxxxx'@'%' //&匹配来自userxxxxxxxxx用户的SQL
FOR SELECT //&匹配是SELECT类型的SQL语句
FILTER BY TEMPLATE('438b00e4','57a572f9','de6eefdb') //&匹配中其中一个模版ID,则该匹配项算匹配成功
WITH MAX_CONCURRENCY = 0; //设置单节点并发度为0,不允许匹配到的SQL执行

如果确定会话中的慢SQL是都是需要限流的烂SQL,且PolarDB-X的CN内核版本为5.4.11以上时,可以开启慢SQL限流。也可以使用实例会话页面里的SQL限流功能,进行如下操作:9..png

总结

SQL限流为应急措施,可在数据库由于烂SQL导致效率降低的时候,起到快速恢复的作用。对烂SQL进行限流后,用户需要将注意力集中在如何优化烂SQL上,并在合适的时机清空SQL限流规则。

相关实践学习
日志服务之使用Nginx模式采集日志
本文介绍如何通过日志服务控制台创建Nginx模式的Logtail配置快速采集Nginx日志并进行多维度分析。
相关文章
|
SQL 运维 监控
【笔记】最佳实践—如何限流慢SQL
本文介绍了如何对慢SQL进行有效限流。
129 0
【笔记】最佳实践—如何限流慢SQL
|
SQL 存储 缓存
【笔记】最佳实践—如何分析及优化慢SQL
本文介绍了分析和解决慢SQL的方法。
119 0
【笔记】最佳实践—如何分析及优化慢SQL
|
SQL 运维 监控
最佳实践—如何限流慢SQL
本文介绍了如何对慢SQL进行有效限流。
131 0
最佳实践—如何限流慢SQL
|
4天前
|
消息中间件 存储 监控
|
5天前
|
存储 关系型数据库 MySQL
PolarDB-X 存储引擎核心技术 | 索引回表优化
数据库系统为了高效地存储、检索和维护数据,采用了多种不同的数据组织结构。不同的组织结构有其特定的用途和优化点,比如提高查询速度、优化写入性能、减少存储空间等,目前 PolarDB-X 采用了 B-Tree 的索引组织结构。
|
7天前
|
弹性计算 Prometheus 监控
基于 Prometheus 的超算弹性计算场景下主机监控最佳实践
超算快速弹性伸缩场景下,如何构建一套准确、快速、可靠的监控体系成为关键点。阿里云在超算场景的主机监控落地实践,解决超算场景面临的挑战,交付一套可靠和全面的主机监控体系。
59283 11
|
2天前
|
存储 云计算 开发者
【预告】阿里云计算新品速递:HPC优化实例商业化发布
5月30日14:00,将推出专为云上高性能计算设计的HPC优化实例hpc8ae,旨在解决现有云计算基础设施对HPC应用优化不足的问题,提供经济高效的仿真解决方案,提升计算效率,加速业务创新。直播中,阿里云专家将展示实例在计算流体、有限元分析等领域的应用,并通过两个云上工业仿真Demo进行实践演示。参与直播还有机会赢取丰富礼品。
【预告】阿里云计算新品速递:HPC优化实例商业化发布
|
7天前
|
人工智能 监控 算法
函数计算助力领健信息为“看牙”注入 AI 活力
口腔治疗+函数计算=效率提升🚀 领健作为业界领先的口腔机构,面向口腔诊所提供正畸算法,但早期的算法部署遇到较多问题,因此在对比了阿里云的多个云产品之后,最终选择了函数计算。 通过将 GPU 计算负载放到函数计算,领健技术团队达到了很好的降本效果,相比早前的按月持有 GPU 资源,函数计算的费用降低了 90% 左右,并大大提升了使用体验,实现了前所未有的敏捷性和效率。
56793 1
|
14天前
|
SQL 容灾 关系型数据库
[版本更新] PolarDB-X V2.4 列存引擎开源正式发布
[版本更新] PolarDB-X V2.4 列存引擎开源正式发布!
[版本更新] PolarDB-X V2.4 列存引擎开源正式发布
|
14天前
|
存储 关系型数据库 分布式数据库
数据管理的艺术:PolarDB开源版详评与实战部署策略(二)
PolarDB-PG是阿里云的一款云原生关系型数据库,100%兼容PostgreSQL,支持Oracle语法,采用Shared-Storage存储计算分离架构,提供极致弹性、毫秒级延迟的HTAP能力。具备高可用、高可靠和弹性扩展特性,支持单机、存储计算分离和X-Paxos三节点等多种部署形态。通过Docker可快速部署实例,包括单节点、一主一备和HTAP(一主两备)实例。此外,文章还介绍了在ECS上使用ESSD云盘搭建PolarDB-PG的详细步骤,适合开发和测试环境。
212024 21

热门文章

最新文章