摘要: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以及设置参数等语句,常量值不会忽略。例如,以下两个查询:

select * from t1 where id = 1;
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%时触发异常退出:

CREATE EXCEPT RULE cpu_percent_except WITH(ELAPSEDTIME=2000, CPUAVGPERCENT=30);

异常规则还支持BLOCKTIME、ALLCPUTIME、SPILLSIZE等异常的识别处理,具体可参考:异常规则简介与演变

3. 创建资源池respool1关联异常规则cpu_percent_except

CREATE RESOURCE POOL respool1 WITH(except_rule='cpu_percent_except');

资源池支持最多关联63个异常规则集,每个异常规则集间独立生效,互不影响。

4. 创建业务用户usr1,关联资源池respool1:

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. 查询作业黑名单和异常信息:

SELECT * FROM dbms_om.gs_blocklist_query;
unique_sql_id | block_list | except_num | except_time
---------------+------------+------------+----------------------------
4066836196 | t | 1 | 2022-08-08 18:00:00.596269
(1 row)

7. 用户usr1再次运行作业触发异常熔断,GaussDB(DWS)的异常熔断机制禁止该作业执行。

ERROR:  The query is in the blocklist and cannot be run, unique_sql_id(4066836196).
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移除黑名单。

select gs_remove_blocklist(4066836196);
gs_remove_blocklist
---------------------
t
(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。

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。示例:

postgres=# explain verbose select count(1) from pg_class;
QUERY PLAN
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
id | operation | E-rows | E-distinct | E-width | E-costs
----+----------------------------------------+--------+------------+---------+---------
1 | -> Aggregate | 2 | | 8 | 52.94
2 | -> Seq Scan on pg_catalog.pg_class | 1034 | | 0 | 50.34
Targetlist Information (identified by plan id)
------------------------------------------------------------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------------------------------------
1 --Aggregate
Output: count(1)
2 --Seq Scan on pg_catalog.pg_class
Output: relname, relnamespace, reltype, reloftype, relowner, relam, relfilenode, reltablespace, relpages, reltuples, relallvisible, reltoastrelid, reltoas
tidxid, reldeltarelid, reldeltaidx, relcudescrelid, relcudescidx, relhasindex, relisshared, relpersistence, relkind, relnatts, relchecks, relhasoids, relhaspkey, r
elhasrules, relhastriggers, relhassubclass, relcmprs, relhasclusterkey, relrowmovement, parttype, relfrozenxid, relacl, reloptions, relreplident, relfrozenxid64
====== Query Summary =====
--------------------------
Parser runtime: 0.027 ms
Planner runtime: 0.561 ms
Unique SQL Id: 2307078791
(17 rows)

2.2.2 将作业加入黑名单

获取到作业Unique SQL ID后,调用内置函数gs_append_blocklist(unique_sql_id int8)将作业加入黑名单:

postgres=# select * from gs_append_blocklist(2307078791);
gs_append_blocklist
---------------------
t
(1 row)

2.2.3 查询黑名单信息

作业加入黑名单后,查询系统表确认黑名单加入是否成功:

postgres=# SELECT * FROM dbms_om.gs_blocklist_query;
unique_sql_id | block_list | except_num | except_time
---------------+------------+------------+-------------
2307078791 | t | 0 |
(1 row)

2.2.4 再次执行作业触发紧急拦截

postgres=# select count(1) from pg_class;
ERROR: The query is in the blocklist and cannot be run, unique_sql_id(2307078791).
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 问题解决,将作业移出黑名单

postgres=# select gs_remove_blocklist(2307078791);
gs_remove_blocklist
---------------------
t
(1 row)

点击关注,第一时间了解华为云新鲜技术~

GaussDB(DWS)查询过滤器原理与应用的更多相关文章

  1. 十八般武艺玩转GaussDB(DWS)性能调优(三):好味道表定义

    摘要:表结构设计是数据库建模的一个关键环节,表定义好坏直接决定了集群的有效容量以及业务查询性能,本文从产品架构.功能实现以及业务特征的角度阐述在GaussDB(DWS)的中表定义时需要关注的一些关键因 ...

  2. 十八般武艺玩转GaussDB(DWS)性能调优:SQL改写

    摘要:本文将系统介绍在GaussDB(DWS)系统中影响性能的坏味道SQL及SQL模式,帮助大家能够从原理层面尽快识别这些坏味道SQL,在调优过程中及时发现问题,进行整改. 数据库的应用中,充斥着坏味 ...

  3. GaussDB(DWS)中共享消息队列实现的三大功能

    摘要:本文将详细介绍GaussDB(DWS)中共享消息队列的实现. 本文分享自华为云社区<GaussDB(DWS)CBB组件之共享消息队列介绍>,作者:疯狂朔朔. 1)共享消息队列是什么? ...

  4. GaussDB(DWS)应用实战:对被视图引用的表进行DDL操作

    摘要:GaussDB(DWS)是从Postgres演进过来的,像Postgres一样,如果表被视图引用的话,特定场景下,部分DDL操作是不能直接执行的. 背景说明 GaussDB(DWS)是从Post ...

  5. 详解GaussDB(DWS) explain分布式执行计划

    摘要:本文主要介绍如何详细解读GaussDB(DWS)产生的分布式执行计划,从计划中发现性能调优点. 前言 执行计划(又称解释计划)是数据库执行SQL语句的具体步骤,例如通过索引还是全表扫描访问表中的 ...

  6. 从数据仓库双集群系统模式探讨,看GaussDB(DWS)的容灾设计

    摘要:本文主要是探讨OLAP关系型数据库框架的数据仓库平台如何设计双集群系统,即增强系统高可用的保障水准,然后讨论一下GaussDB(DWS)的容灾应该如何设计. 当前社会.企业运行当中,大数据分析. ...

  7. GaussDB(DWS)应用实践丨负载管理与作业排队处理方法

    摘要:本文用来总结一些GaussDB(DWS)在实际应用过程中,可能出现的各种作业排队的情况,以及出现排队时,我们应该怎么去判断是否正常,调整一些参数,让资源分配与负载管理更符合当前的业务:或者在作业 ...

  8. 由两个问题引发的对GaussDB(DWS)负载均衡的思考

    摘要:GaussDB(DWS)的负载均衡通过LVS+keepAlived实现.对于这种方式,需要思考的问题是,CN的返回结果是否会经过LVS,然后再返回给前端应用?如果经过LVS,那么,LVS会不会成 ...

  9. 十八般武艺玩转GaussDB(DWS)性能调优:路径干预

    摘要:路径生成是表关联方式确定的主要阶段,本文介绍了几个影响路径生成的要素:cost_param, scan方式,join方式,stream方式,并从原理上分析如何干预路径的生成. 一.cost模型选 ...

  10. 探索GaussDB(DWS)的过程化SQL语言能力

    摘要:在当前GaussDB(DWS)的能力中主要支持两种过程化SQL语言,即基于PostgreSQL的PL/pgSQL以及基于Oracle的PL/SQL.本篇文章我们通过匿名块,函数,存储过程向大家介 ...

随机推荐

  1. 当个 PM 式程序员「GitHub 热点速览」

    本周 GitHub 热点依旧是 GPT 类项目,当中的佼佼者自然是本文收录的 gpt-pilot,一周获得了 7k+ star.此外,像是 LangChain.Autogen 之类的 LLM 工具链项 ...

  2. [CF1178 F2] Long Colorful Strip

    F2 - Long Colorful Strip 很牛的题! 首先,我们可以将颜色相同的一段区间缩成一个点,那么每次加入一个新的颜色时,最多只能将其所覆盖的那个颜色所属的区间分成三部分(原本:0000 ...

  3. Util应用框架Web Api开发快速入门

    本文是使用Util应用框架开发 Web Api 项目快速入门教程. 前面已经详细介绍了环境搭建,如果你还未准备好,请参考前文. 开发流程概述 创建代码生成专用数据库. Util应用框架需要专门用来生成 ...

  4. Rustlings通关记录与题解

    2023年6月19日决定对rust做一个重新的梳理,整理今年4月份做完的rustlings,根据自己的理解来写一份题解,记录在此. 周折很久,因为中途经历了推免的各种麻烦事,以及选择数据库作为未来研究 ...

  5. 导出所有容器id号

    #!/bin/bash a=`docker ps|awk 'NR>1{print $1}'` FORMAT="%-12s\t,\t%-12s\t,\t%-12s\n" pri ...

  6. P5445 [APIO2019] 路灯 题解

    题目链接 题目描述 给你一个 01 串,有 \(q\) 个时刻,每个时刻要么把一位取反,要么问你在过去的所有时刻中有多少个时刻 \(a\) 和 \(b-1\) 之间都为 1. 题目分析 观察题目,我们 ...

  7. DOT 学习笔记

    开始大恶补图论了. 说句闲话,\(\text{ODT}\) 和 \(\text{DOT}\). \(\text{DOT}\),全称「树上启发式合并(\(\text{dsu on tree}\))」,乍 ...

  8. 自实现string类

    一. 环境 Linux x86_64,g++ 8.5.0 二. 实现 自实现 string 之前一直想写来着,一直拖着,现在把它完稿.这个版本是比较简单的版本,有一些可能有不同的或者更好的实现方式,后 ...

  9. CSS(不定时更新)

    一.使用img后的高度多了4px 由于img是行内元素,默认display: inline; 它与文本的默认行为类似,下边缘是与基线(baseline)对齐,而不是紧贴容器下边缘. 将displayp ...

  10. Socket是什么/怎么理解Socket

    Socket 先来看一下百度百科对于Socket的介绍:套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开.读写和关闭等操作.套接字允许应用程序将I/O ...