更新时间:2025-11-03 GMT+08:00
分享

CREATE BLOCK RULE

功能描述

该语法用于创建一条查询过滤规则,包括查询过滤规则名称、绑定的客户端名称、客户端IP、用户以及匹配方式等。在日常数据库操作中,异常SQL的执行可能会导致资源过度消耗,影响数据库性能和稳定性,通过创建查询过滤规则,可以将此类SQL语句进行拦截。

当前支持指定某个SQL语句的正则匹配进行拦截,例如针对某用户对某张表的SELECT进行拦截;也支持指定某SQL语句的unique_sql_id或sql_hash取值进行拦截,例如已知某SQL语句的unique_sql_id值,将此SQL语句直接拦截。

本文档提供基础SQL语法,您也可以通过控制台进行配置,参见使用DWS查询过滤器拦截慢SQL

注意事项

  • 该语法仅9.1.0.100及以上集群版本支持。
  • 只有拥有数据库所有者权限的用户或者授予gs_role_block角色权限的用户才能执行CREATE BLOCK RULE命令,系统管理员默认拥有此权限。
  • 普通用户无法执行CREATE BLOCK RULE,可通过系统管理员进行授权,授权语法:
    1
    GRANT gs_role_block TO user;
    

    建议创建查询过滤规则时尽量缩小适用范围,避免误过滤,或者范围过大导致性能劣化

语法格式

1
2
3
4
5
6
CREATE BLOCK RULE [ IF NOT EXISTS ] block_name
    [ [ TO user_name@'host' ] | [ TO user_name ] | [ TO 'host' ] ] |
    [ FOR UPDATE | SELECT | INSERT | DELETE | MERGE ] |
    FILTER BY
    { SQL ( 'text' ) | TEMPLATE ( template_parameter = value ) }
    [ WITH ( { with_parameter = value }, [, ... ] ) ];

参数说明

表1 CREATE BLOCK RULE参数说明

参数

描述

取值范围或示例

block_name

要创建的查询过滤规则名称。

字符串,需符合标识符命名规范

TO

对查询过滤规则生效的对象或客户端IP,支持以下方式:

  • TO user_name@'host':用户名以及客户端IP,两者都要满足,查询过滤规则才能生效。
  • TO user_name:用户名,即只判定满足用户名条件,查询过滤规则就生效,不区分客户端IP。
  • TO 'host':客户端IP,即只判定满足客户端IP条件,查询过滤规则就生效,不区分用户。

举例:查询过滤规则对来自客户端IP为192.168.0.59且登录用户名为user1时生效。

1
CREATE BLOCK RULE query_block TO user1@'192.168.0.59' FOR SELECT  FILTER BY SQL('test.test');     

查询过滤规则对登录用户名为user1时生效(无论客户端IP是哪个)。

1
CREATE BLOCK RULE query_block TO user1 FOR SELECT  FILTER BY SQL('test.test');  

查询过滤规则对来自客户端IP 192.168.0.59的访问时都生效(无论哪个用户登录)。

1
CREATE BLOCK RULE query_block TO '192.168.0.59' FOR SELECT  FILTER BY SQL('test.test');  

FOR

语句类型,支持对UPDATE/SELECT/INSERT/DELETE/MERGE INTO五种类型语句进行限制。

-

FILTER BY

过滤方法,支持两种形式:

  • SQL:根据SQL语句内容进行过滤,通过关键词对语句进行正则匹配,例如表名,其长度不能超过1024,建议尽量精简。
  • TEMPLATE:根据模板进行过滤,此方法不区分用户,针对所有用户执行的特定语句都实施拦截,拦截效果更高效,取值如下:
    • unique_sql_id:归一化的64位哈希值,重复概率较sql_hash大一些。
    • sql_hash:归一化的哈希值(MD5),一般不会重复,相较unique_sql_id更推荐使用。

unique_sql_id和sql_hash取值,可以通过EXPLAIN VERBOSE查询,例如:

1
EXPLAIN VERBOSE SELECT * FROM test.test;

with_parameter

查询过滤规则选项参数。

以下选项可以一起设置,满足任何一个参数的限制查询将会被过滤。

  • application_name,客户端名称。
  • query_band,负载标识。
  • table_num,语句扫描的基表个数。
  • partition_num,算子预估扫描的最大分区数。
  • estimate_row,算子预估扫描的最大表行数。
  • resource_pool,需要切换到的资源池名称。
  • max_active_num,规则对应语句的最大并发数。
  • is_warning,控制拦截到语句的行为是告警还是报错,on表示告警,off表示报错,默认为off。

示例:基于匹配SQL语句进行SQL拦截

以系统管理员连接数据库执行以下SQL,创建一个名为src的临时表,为后续的INSERT操作提供数据源。
1
2
CREATE SCHEMA test;
CREATE TABLE test.src AS SELECT 1;
执行以下SQL,创建表test.test。
1
2
DROP TABLE IF EXISTS test.test;
CREATE TABLE test.test(a int, b numeric(15,2)) WITH(orientation=column);
执行以下SQL,分别为两张表插入2000万行数据。执行时间约半分钟,请等待。
1
INSERT INTO test.test SELECT generate_series(1,20000000) % 1000,generate_series(1,20000000) FROM test.src;

创建用户user1,并授权该用户可以访问表test.test。

1
2
3
CREATE USER user1 PASSWORD "password";
GRANT USAGE ON SCHEMA test TO user1;
GRANT SELECT ON TABLE test.test TO user1;

以用户user1连接数据库,查询表数据,结果表明在没有创建过滤规则的情况下,用户user1可以正常查询表test.test数据。

1
SELECT sum(b) FROM test.test GROUP BY a;

以系统管理员连接数据库,创建名称为query_block的查询过滤规则,对于用户user1查询的SQL语句进行拦截,过滤方式为SQL语句,SQL语句中出现关键字test(即表名)会被过滤。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
CREATE BLOCK RULE query_block 
TO user1@'192.168.0.59'        --规则作用于用户user1,且客户端IP为192.168.0.59。
FOR SELECT                     --过滤SELECT的相关操作。
FILTER BY 
SQL('test.test')               --过滤方式为SQL语句,SQL语句中出现关键字test(即表名)会被过滤。
WITH                           --满足以下条件即被过滤。
(                             
application_name='gsql',       --客户端名称为gsql
table_num='1',                 --扫描基表次数为1 
estimate_row='10',             --扫描基表行数为10
is_warning='off'               --关闭告警,直接报错
)
;

通过视图pg_get_blockruledef查询已创建的过滤规则,从回显判断出规则已生效。

1
SELECT * FROM pg_get_blockruledef('query_block');

切换回user用户连接数据库,再次查询以下SQL,报以下类似信息错误,ERROR: hit block rule query_block xxx,表示语句被拦截了。

1
SELECT sum(b) FROM test.test GROUP BY a;

示例:基于语句的unique_sql_id值或sql_hash值进行SQL拦截

继续如上示例,切换回系统管理员连接数据库,执行以下命令查询unique_sql_id和sql_hash。

1
EXPLAIN VERBOSE  SELECT sum(b) FROM test.test GROUP BY a;

从回显中记录unique_sql_id和sql_hash。

删除原来的过滤规则,创建基于unique_sql_id的过滤规则。

1
2
DROP BLOCK RULE query_block;
CREATE BLOCK RULE query_block FILTER BY TEMPLATE(unique_sql_id='3324222175');

再次切到user1用户,查询报错,语句被拦截了。

1
SELECT sum(b) FROM test.test GROUP BY a;

同样,以系统管理员去执行一遍,语句会被拦截,由此可知,通过unique_sql_id进行过滤拦截,并不区分用户,对所有用户执行此类SQL语句都会进行拦截,拦截效果更优。

1
SELECT sum(b) FROM test.test GROUP BY a;

删除过滤规则,创建基于sql_hash的过滤规则。

1
2
DROP BLOCK RULE query_block;
CREATE BLOCK RULE query_block FILTER BY TEMPLATE(sql_hash='sql_170d0c75c472043b0cd35e05903c382f');

再次切到user1用户,查询报错,语句被拦截了。

相关链接

ALTER BLOCK RULEDROP BLOCK RULE

本文档提供基础SQL语法,您也可以通过控制台进行配置,参见使用DWS查询过滤器拦截慢SQL

相关文档