添加SQL防御规则
用户可以在CloudTable ClickHouse集群详情界面添加SQL防御规则,系统会对触发规则的SQL请求进行提示、拦截或阻断操作。
为ClickHouse集群添加或者修改SQL防御规则时需结合业务场景进行规则是否开启以及对应规则阈值是否合理的评估,不合理的防御规则对相关SQL请求进行拦截或阻断后,可能会对上层业务造成影响。
前提条件
- 已创建ClickHouse集群,且集群运行正常。
- 已安装ClickHouse客户端。
添加SQL防御规则
- 登录表格存储服务控制台。
- 进入“集群管理”页面,单击目标集群进入集群详情页面。
- 在左侧导航栏选择“SQL防御”,进入SQL防御规则管理页面,可单击页面左上角的“规则说明”按钮查看当前集群支持的所有SQL防御规则介绍。
- 单击规则列表页面左上角的“新建规则”,打开新建规则页面。
- 配置相关参数后,单击“确定”添加规则。
- 单次最多支持添加10条规则。
- 同一对象不支持多次配置相同规则ID和拦截动作。
- 拦截阈值需大于提示阈值。
表1 添加规则 参数
描述
规则名称
自定义SQL防御规则名称,支持大小写英文字母、数字和下划线,但必须以字母开头,长度不超过64个字符。
规则名称仅用于标识,允许重名。
规则ID
选择规则ID。
不同ID对应的防御规则含义信息可参考表 SQL防御规则。
生效对象
当前仅支持用户。
对象名称
防御规则绑定的用户名。绑定用户后,该规则将作用于该用户对应的SQL。
- 提示及阈值
- 拦截及阈值
- 熔断及阈值
单击按钮启用提示、拦截或熔断SQL防御规则,并配置对应的阈值参数。防御规则及阈值参数详细说明请参见表2。
SQL请求满足防御规则后,系统的处理操作有以下类型:- 提示:配置系统对SQL请求满足防御规则后,是否进行提示处理。
- 拦截:配置系统对SQL请求满足防御规则后,是否进行拦截处理。
- 熔断:配置系统对SQL请求满足防御规则后,是否进行熔断处理。
说明:对于规则类型为静态拦截、动态拦截的SQL防御规则,系统支持“提示”、“拦截”操作。对于规则类型为运行熔断的SQL防御规则,系统支持“熔断”操作。
操作
删除当前待添加的规则。如果当前仅有一条规则,则无法执行删除操作。
- 规则添加成功后,可以在“SQL防御”界面查看已添加的防御规则。
如需对当前规则进行调整,可单击对应规则所在“操作”列的“修改”或删除,可修改规则相关参数或删除该规则,删除规则时需要进行二次确认。
图1 查看SQL防御规则
- 验证SQL防御规则是否生效。例如:
- 给用户admin设置了static_0003的防御规则,提示和拦截的阈值分别为1和2,该规则是用于检查SQL中join次数是否超过配置的阈值。
- 使用ClickHouse客户端连接ClickHouse集群,具体操作请参见5.6.3 使用客户端连接ClickHouse普通集群或5.6.4 使用客户端连接ClickHouse安全集群。
- 执行select join on命令,分别join 2次和3次,验证是否触发static_0003的提示和拦截动作。
- 2次join操作触发提示动作:
select * from t1 join t2 on t1.id = t2.id join t3 on t1.id = t3.id;
图2 2次join命令触发提示信息
- 3次join操作触发拦截动作:
select * from t1 join t2 on t1.id = t2.id join t3 on t1.id = t3.id join t4 on t1.id = t4.id;
命令执行后,SQL会被拦截。
图3 命令被拦截
- 2次join操作触发提示动作:
SQL防御规则
| 规则ID | 规则描述 | 规则变量参数 | 阈值取值范围 | SQL语句示例 | 影响分析 | 触发拦截/熔断时的错误信息样例 |
|---|---|---|---|---|---|---|
| static_0003 | SQL中的join次数超限制。 | join次数阈值。 建议配置值:20 | [1-10000] | N/A | join的表越多,扫描的文件、分区、数据量越多,会导致SQL内存占用过多,影响集群稳定性。 | Code: 392. DB::Exception: Number of joins in the query is 6, which is more than the allowed limit 5. (QUERY_IS_PROHIBITED) |
| static_0004 | SQL中的union all次数超限制。 | union all次数阈值。 建议配置值:20 | [1-10000] | select * from tables t1 union all select * from tables t2 union all select * from tables t3 union all select * from tables t4 union all select * from tables t5 union all select * from tables t6 union all select * from tables t7 union all select * from tables t8 union all select * from tables t9; | 大量union all可能产生超大结果集,占用大量资源。 | Code: 392. DB::Exception: number of union in the query 6 is more than the allowed limit 5. (QUERY_IS_PROHIBITED) |
| static_0005 | 子查询嵌套层数超限制。 | 子查询的嵌套层数。 建议配置值:20 | [1-10000] | select * from ( with temp1 as (select * from tables) select * from temp1); | SQL嵌套层数过多,多次生成临时数据,且SQL不易维护修改,建议优化SQL,避免多重嵌套查询,提升执行效率和SQL可维护性。 | Code: 392. DB::Exception: Number of nested subqueries in the query is 6, which is more than the allowed limit 5. (QUERY_IS_PROHIBITED) |
| static_0008 | 在集群级别(on cluster)执行alter table update操作。 | N/A | N/A | alter table testtb1 on cluster default_cluster update price=10.0 where id='100'; | 更新数据、删除数据操作需要消耗较多CPU和内存资源,在集群级别操作会给数据库带来过高的压力,可能引起部分节点任务执行失败、超时、长时间无响应等现象,影响集群稳定性。 | Code: 392. DB::Exception: Distributed DDL ALTER UPDATE queries are prohibited. (QUERY_IS_PROHIBITED) |
| static_0009 | 在集群级别(on cluster)执行alter table delete操作。 | N/A | N/A | alter table testtb1 on cluster default_cluster delete where id ='10'; | Code: 392. DB::Exception: Distributed DDL ALTER DELETE queries are prohibited. (QUERY_IS_PROHIBITED) | |
| static_0010 | 在集群级别(on cluster)执行alter table add column操作。 | N/A | N/A | alter table testtb1 on cluster default_cluster add column testc String; | 添加列、删除列操作需要消耗较多CPU和内存资源,在集群级别操作会给数据库带来过高的压力,可能引起部分节点任务执行失败、超时、长时间无响应等现象,造成元数据不一致,影响集群稳定性。 | Code: 392. DB::Exception: Distributed DDL ALTER ADD COLUMN queries are prohibited. (QUERY_IS_PROHIBITED) |
| static_0011 | 在集群级别(on cluster)执行alter table drop column操作。 | N/A | N/A | alter table testtb1 on cluster default_cluster drop column testc; | Code: 392. DB::Exception: Distributed DDL ALTER DROP COLUMN queries are prohibited. (QUERY_IS_PROHIBITED) | |
| static_0012 | 在集群级别(on cluster)执行optimize final操作。 | N/A | N/A | optimize table testtb1 on cluster default_cluster final; | 手动合并操作在表数据量较大的场景下,需要消耗较多CPU和内存资源,并占用大量的磁盘IO;在集群级别操作会给数据库带来过高的压力,可能引起部分节点任务执行失败、超时、长时间无响应等不稳定现象,影响集群稳定性。 | Code: 392. DB::Exception: Distributed DDL OPTIMIZE FINAL queries are prohibited. (QUERY_IS_PROHIBITED) |
| static_0013 | 在集群级别(on cluster)执行drop类操作。 | N/A | N/A | drop table/database test on cluster default_cluster; | 销毁表操作在表元数据和数据量较大的场景下,需要消耗较多CPU和内存资源,并占用大量的磁盘IO;在集群级别操作会给数据库带来过高的压力,可能引起部分节点任务执行失败、超时、长时间无响应等不稳定现象,影响集群稳定性。 | Code: 392. DB::Exception: Distributed DDL DROP TABLE queries are prohibited. (QUERY_IS_PROHIBITED) |
| static_0014 | 在集群级别(on cluster)执行truncate table操作。 | N/A | N/A | truncate table testtb1 on cluster default_cluster; | 删除表数据的操作在表数据量较大的场景下,需要消耗较多CPU和内存资源,并占用大量的磁盘IO;在集群级别操作会给数据库带来过高的压力,可能引起部分节点任务执行失败、超时、长时间无响应等不稳定现象,影响集群稳定性。 | Code: 392. DB::Exception: Distributed DDL TRUNCATE TABLE queries are prohibited. (QUERY_IS_PROHIBITED) |
| static_0015 | 写入分布式表操作。 | N/A | N/A | insert into db.distribute_table values('2022-01-20', '1'); | 分布式表写入会立刻返回成功,但实际后台执行是一个异步写入的过程。当节点压力大或待写入数据存在异常数据时,会导致后台数据写入失败,持续消耗资源,影响集群稳定,且存在部分用户数据丢失风险。 | Code: 392. DB::Exception: Insert to distributed table queries are prohibited. (QUERY_IS_PROHIBITED) |
| static_0016 | SQL中select列数超过阈值。 | 查询列数阈值。 建议配置值:100 | [1-10000] | select * from db.table1; | 查询结果包含大量列的SQL语句在执行时会消耗大量资源,导致集群稳定性下降,影响其他任务正常运行。 | Code: 392. DB::Exception: Number of columns read is 6. which is more than the allowed limit 5. (QUERY_IS_PROHIBITED) |
| dynamic_0002 | 对单个表操作(select、delete、update、alter)涉及的分区数超限制。 | 表操作所涉及的分区数量阈值。 建议配置值:10000 | [1-10000000] | DELETE FROM table_name WHERE column_name = value; | 扫描分区量过多可能对服务造成压力,导致服务慢SQL。 | Code: 565. DB::Exception: Too many partitions to read. Current 6, max 5. (TOO_MANY_PARTITIONS) |
| dynamic_0003 | 执行join操作时,右表的数据量超限制。 | 执行join操作时,右表的行数阈值。 建议配置值:100000000 | [1-1000000000] | SELECT name, text FROM table_1 JOIN table_2 ON table_1.Id = table_2.Id; | 当右表数据量过大时,会造成join操作占用大量的内存,可能导致内存不足的异常,造成业务执行失败,影响集群稳定性。 | Code: 191. DB::Exception: Limit for JOIN exceeded, max rows: 1.00, current rows: 5.00: While executing FillingRightJoinSide. (SET_SIZE_LIMIT_EXCEEDED) |
| running_0001 | Select类型的SQL语句向客户端返回的结果行数超限制。 | 查询返回结果的行数阈值。 建议配置值:100000 | [1-1000000000] | select * from table; | 一次性返回的查询结果过多会导致服务端临时内存开销过大,产生OOM异常,影响服务端稳定性,同时,一次性查询结果集过大也会导致查询效率低。 | Code: 396. DB::Exception: Limit for result exceeded, max rows: 10.00, current rows: 100.00. (TOO_MANY_ROWS_OR_BYTES) |
| running_0002 | SQL的占用内存峰值超绝对值限制。 | SQL运行占用内存阈值,单位为MB。 | [1-1024000] | N/A | 大任务会长时间占用集群CPU和内存资源,影响其他任务执行,影响集群整体性能。 | Code: 241. DB::Exception: Memory limit (for query) exceeded: would use 14.52 MiB (attempt to allocate chunk of 4367996 bytes), maximum: 9.54 MiB.: While executing MergeTreeSelect(pool: ReadPool, algorithm: Thread). (MEMORY_LIMIT_EXCEEDED) |
| running_0003 | SQL已经运行的时长超限制。 | SQL运行时长阈值,单位为秒。 | [1-259200] | N/A | 任务长时间运行将持续占用集群资源,影响集群资源利用率,并且可能产生大量中间数据,不符合预期的任务需要及时调整。 | Code: 159. DB::Exception: Timeout exceeded: elapsed 1.000222433 seconds, maximum: 1. (TIMEOUT_EXCEEDED) |
| running_0004 | SQL已经发生的数据扫描量超过阈值。 | SQL扫描数据量,单位为GB。 | [1-10000000] | N/A | 扫描过多的数据量会占用大量的集群计算资源和IO资源,影响其他任务的正常执行。 | Code: 307. DB::Exception: Limit for rows or bytes to read exceeded, max bytes: 1.00 MiB, current bytes: 2.76 MiB: While executing MergeTreeSelect(pool: ReadPool, algorithm: Thread). (TOO_MANY_BYTES) |