翼度科技»论坛 编程开发 mysql 查看内容

GaussDB(DWS)查询过滤器原理与应用

4

主题

4

帖子

12

积分

新手上路

Rank: 1

积分
12
摘要:GaussDB(DWS)查询过滤器(黑名单)提供查询过滤功能,支持自动隔离反复被终止的查询,防止烂SQL再次执行。
本文分享自华为云社区《GaussDB(DWS)查询过滤器原理与应用》,作者:门前一棵葡萄树 。
一、概述

GaussDB(DWS)查询过滤器(黑名单)提供查询过滤功能,支持自动隔离反复被终止的查询,防止烂SQL再次执行。
主要应用场景包含以下两种:
1. 异常熔断机制
配置异常规则后,查询触发异常规则后,异常信息将被记录在dbms_om.gs_blocklist_query系统表中。同一个查询触发异常规则次数超限(query_exception_count_limit)后,查询自动加入黑名单,黑名单信息同样保存在dbms_om.gs_blocklist_query系统表中。加入黑名单后,该查询将被隔离,拒绝执行。
2. 紧急拦截
作业引发CORE、hang或性能大幅下降等问题时,需要紧急规避时,可以将作业加入黑名单进行过滤。
原理介绍

查询过滤器使用作业Unique SQL ID保存和识别作业黑名单和异常信息,在SQL中常数值发生变化时作业Unique SQL ID不会随之发生变化。Unique SQL ID是遍历查询解析树计算出来的一个整数值,用于标识一类SQL。通常对于DML语句,在计算Unique SQL ID的过程中会忽略常量值。但对于DDL、DCL以及设置参数等语句,常量值不会忽略。例如,以下两个查询:
  1. select * from t1 where id = 1;
  2. select * from t1 where id = 2;
复制代码
这两条SQL除过滤条件中的常量不同外,其他全部相同,由此生成的解析树拓扑完全相同,因此Unique SQL ID相同。Unique SQL ID的计算只会忽略常数值,而不会忽略其他差异,SQL语句“select * from t2 where id = 1;”与上述两个SQL的Unique SQL ID就不相同。
将作业加入黑名单主要有以下两种方式:

  • 在GUC参数query_exception_count_limit≥0情况下,作业触发异常次数超过该阈值后自动将作业加入黑名单;
  • 调用内置函数gs_append_blocklist(unique_sql_id int8)将作业加入黑名单。
作业执行前判断作业是否在黑名单中,如果作业在黑名单中,拒绝作业执行,直接报错退出。
作业被拒绝执行后,对作业加入黑名单原因进行分析,问题解决后调用内置函数gs_remove_blocklist(unique_sql_id int8)将作业移除黑名单。
二、应用示例

2.1 异常熔断示例

1. 设置异常熔断阈值。假设设置query_exception_count_limit=1,即只要作业触发异常规则作业就会被加入黑名单。
2. 配置异常规则
创建CPU平均使用率异常规则cpu_percent_except,作业运行时间超过2000秒且CPU使用率达到30%时触发异常退出:
  1. CREATE EXCEPT RULE cpu_percent_except WITH(ELAPSEDTIME=2000, CPUAVGPERCENT=30);
复制代码
异常规则还支持BLOCKTIME、ALLCPUTIME、SPILLSIZE等异常的识别处理,具体可参考:异常规则简介与演变
3. 创建资源池respool1关联异常规则cpu_percent_except
  1. CREATE RESOURCE POOL respool1 WITH(except_rule='cpu_percent_except');
复制代码
资源池支持最多关联63个异常规则集,每个异常规则集间独立生效,互不影响。
4. 创建业务用户usr1,关联资源池respool1:
  1. CREATE USER usr1 RESOURCE POOL 'respool1' PASSWORD 'XXXXXX';
复制代码
5. 用户usr1运行作业,作业运行时间超过2000秒且CPU使用率达到30%时触发“cpu_percent_except”异常规则,作业触发异常规则后资源管理对作业进行以下处理:

  • 将作业异常信息保存至系统表GS_BLOCKLIST_QUERY中;
  • 如果作业触发异常熔断,将系统表GS_BLOCKLIST_QUERY中作业黑名单标志置为true;
  • 更新GS_BLOCKLIST_QUERY中作业黑名单信息。
6. 查询作业黑名单和异常信息:
  1. SELECT * FROM dbms_om.gs_blocklist_query;
  2. unique_sql_id | block_list | except_num | except_time
  3. ---------------+------------+------------+----------------------------
  4. 4066836196 | t          | 1 | 2022-08-08 18:00:00.596269
  5. (1 row)
复制代码
7. 用户usr1再次运行作业触发异常熔断,GaussDB(DWS)的异常熔断机制禁止该作业执行。
  1. ERROR:  The query is in the blocklist and cannot be run, unique_sql_id(4066836196).
  2. HINT:  If you want to run the query later, confirm the reason why the query is blocklisted and remove the query from the blocklist after resolving the problem.
复制代码
8. 优化用户usr1所运行ID为4066836196的SQL后,将ID为4066836196的SQL从黑名单移除。
确认SQL异常原因,如果异常规则配置不合理,修改异常规则;如果异常规则合理,对SQL进行优化后重新运行。确认问题解决后将SQL移除黑名单。
  1. select gs_remove_blocklist(4066836196);
  2. gs_remove_blocklist
  3. ---------------------
  4. t
  5. (1 row)
复制代码
2.2 紧急拦截示例

查询过滤器使用作业Unique SQL ID识别和保存黑名单信息,为有效运用查询过滤器紧急拦截功能,建议TopSQL开启,在作业引发CORE、报错、性能下降等问题时可以快速获取作业Unique SQL ID。
2.2.1 获取作业Unique SQL ID

获取作业Unique SQL ID的几种方法:
1. 作业引发报错/性能下降
CN日志中获取作业query_id,执行以下命令查询作业Unique SQL ID。
  1. select queryid,unique_sql_id,query from pgxc_wlm_session_info where queryid=query_id;
复制代码
2. 作业引发CN示例CORE
解析CORE打印内存中保存的Unique SQL ID对应的变量参数值。
3. 作业引发DN实例CORE
作业引发DN实例CORE时,CN侧体现为作业报错,Unique SQL ID获取方式可以参考作业报错时Unique SQL ID获取方式。
4. EXPLAIN VERBOSE获取Unique SQL ID(通用方法,但是仅821及以上版本支持)
EXPLAIN VERBOSE不会实际执行SQL,因此一般不会导致问题发生,使用EXPLAIN VERBOSE XXX;可以打印得到作业Unique SQL ID。示例:
  1. postgres=# explain verbose select count(1) from pg_class;
  2.                                                                            QUERY PLAN
  3. -------------------------------------------------------------------------------------------------------------------------------------------------------------------
  4. -------------------------------------------------------------------------------------------------------------------------------------------------------------------
  5. -----------------------------------------------------------------------------------------------------------------------------------------------------------------
  6.   id |               operation                | E-rows | E-distinct | E-width | E-costs
  7. ----+----------------------------------------+--------+------------+---------+---------
  8. 1 | ->  Aggregate | 2 | | 8 | 52.94
  9. 2 | ->  Seq Scan on pg_catalog.pg_class | 1034 | | 0 | 50.34
  10. Targetlist Information (identified by plan id)
  11. ------------------------------------------------------------------------------------------------------------------------------------------------------------------
  12. -------------------------------------------------------------------------------------------------------------------------------------------------------------------
  13. ----------------------------------------------------------------------------------------------------------------------------------------------------------------
  14. 1 --Aggregate
  15.          Output: count(1)
  16. 2 --Seq Scan on pg_catalog.pg_class
  17.          Output: relname, relnamespace, reltype, reloftype, relowner, relam, relfilenode, reltablespace, relpages, reltuples, relallvisible, reltoastrelid, reltoas
  18. tidxid, reldeltarelid, reldeltaidx, relcudescrelid, relcudescidx, relhasindex, relisshared, relpersistence, relkind, relnatts, relchecks, relhasoids, relhaspkey, r
  19. elhasrules, relhastriggers, relhassubclass, relcmprs, relhasclusterkey, relrowmovement, parttype, relfrozenxid, relacl, reloptions, relreplident, relfrozenxid64
  20. ====== Query Summary =====
  21. --------------------------
  22. Parser runtime: 0.027 ms
  23. Planner runtime: 0.561 ms
  24. Unique SQL Id: 2307078791
  25. (17 rows)
复制代码
2.2.2 将作业加入黑名单

获取到作业Unique SQL ID后,调用内置函数gs_append_blocklist(unique_sql_id int8)将作业加入黑名单:
  1. postgres=# select * from gs_append_blocklist(2307078791);
  2. gs_append_blocklist
  3. ---------------------
  4. t
  5. (1 row)
复制代码
2.2.3 查询黑名单信息

作业加入黑名单后,查询系统表确认黑名单加入是否成功:
  1. postgres=# SELECT * FROM dbms_om.gs_blocklist_query;
  2. unique_sql_id | block_list | except_num | except_time
  3. ---------------+------------+------------+-------------
  4. 2307078791 | t          | 0 |
  5. (1 row)
复制代码
2.2.4 再次执行作业触发紧急拦截
  1. postgres=# select count(1) from pg_class;
  2. ERROR:  The query is in the blocklist and cannot be run, unique_sql_id(2307078791).
  3. HINT:  If you want to run the query later, confirm the reason why the query is blocklisted and remove the query from the blocklist after resolving the problem.
复制代码
2.2.5 问题解决,将作业移出黑名单
  1. postgres=# select gs_remove_blocklist(2307078791);
  2. gs_remove_blocklist
  3. ---------------------
  4. t
  5. (1 row)
复制代码
 
点击关注,第一时间了解华为云新鲜技术~

来源:https://www.cnblogs.com/huaweiyun/p/17463417.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

举报 回复 使用道具