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,可通过系统管理员进行授权,授权语法:
1GRANT 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 }, [, ... ] ) ]; |
参数说明
|
参数 |
描述 |
取值范围或示例 |
||||||
|---|---|---|---|---|---|---|---|---|
|
block_name |
要创建的查询过滤规则名称。 |
字符串,需符合标识符命名规范。 |
||||||
|
TO |
对查询过滤规则生效的对象或客户端IP,支持以下方式:
|
举例:查询过滤规则对来自客户端IP为192.168.0.59且登录用户名为user1时生效。
查询过滤规则对登录用户名为user1时生效(无论客户端IP是哪个)。
查询过滤规则对来自客户端IP 192.168.0.59的访问时都生效(无论哪个用户登录)。
|
||||||
|
FOR |
语句类型,支持对UPDATE/SELECT/INSERT/DELETE/MERGE INTO五种类型语句进行限制。 |
- |
||||||
|
FILTER BY |
过滤方法,支持两种形式:
|
unique_sql_id和sql_hash取值,可以通过EXPLAIN VERBOSE查询,例如:
|
||||||
|
with_parameter |
查询过滤规则选项参数。 |
以下选项可以一起设置,满足任何一个参数的限制查询将会被过滤。
|
示例:基于匹配SQL语句进行SQL拦截
1 2 |
CREATE SCHEMA test; CREATE TABLE test.src AS SELECT 1; |
1 2 |
DROP TABLE IF EXISTS test.test; CREATE TABLE test.test(a int, b numeric(15,2)) WITH(orientation=column); |
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用户,查询报错,语句被拦截了。





