配置SQL防御规则
什么是SQL防御
大数据领域的SQL引擎层出不穷,在带给解决方案多样性的同时,也暴露出一定的问题,例如SQL输入语句质量良莠不齐、SQL问题难定位、大SQL语句消耗资源过多等。
低质量的SQL会对数据分析平台系统带来不可预料的冲击,影响系统的性能或者平台稳定性。
DLI在Spark SQL引擎中增加SQL防御能力,基于用户可理解的SQL防御策略,实现对典型大SQL、低质量SQL的主动防御,包括事前提示、拦截和事中熔断,并不强制改变用户的SQL提交方式、SQL语法,对业务零改动且易实施。
- DLI支持可视化配置SQL防御策略,同时可支持防御规则的查询和修改。
- 每个SQL引擎在进行SQL业务响应、执行过程中,基于SQL防御策略进行主动防御行为。
- 管理员可将SQL防御行为在“提示”、“拦截”、“熔断”选项之间进行灵活切换,系统会将发生的SQL防御事件实时写入到防御审计日志中。运维人员可进行日志分析,评估现网SQL质量,提前感知潜在SQL风险,并做出有效预防措施。
本节操作介绍创建SQL防御规则以增加SQL防御能力的配置方法。
DLI SQL防御规则约束与限制
- 仅Spark 3.3.x及以上版本支持SQL防御功能。
- 同一个队列,同一个动作的防御规则仅支持创建一条。
- 每条规则最多可以关联50个SQL队列。
- 每个项目最多可以创建1000条规则。
- 请勿删除DLI预置的系统防御规则
- 建议您不要删除DLI系统默认创建的规则,避免因大SQL作业耗尽队列资源。
以下规则为系统默认创建的规则:Scan files number、Scan partitions number、Shuffle data(GB)、Count(distinct) occurrences、Not in<Subquery>详细信息参考表2。
创建SQL防御规则
您可以在DLI SQL防御界面对指定SQL队列添加SQL防御规则,系统会对触发规则的SQL请求进行提示、拦截或熔断操作。

添加或者修改SQL防御规则时请结合业务场景评估规则的开启、规则阈值是否合理,避免不合理的防御规则对相关SQL请求进行拦截或阻断后,对业务造成影响。
- 登录DLI管理控制台。
- 选择“全局配置 > SQL防御”,打开SQL防御页面。
- 单击“创建规则”,编辑规则信息。
表1 SQL防御规则参数配置 参数
说明
规则名称
自定义SQL防御规则名称。
系统规则
选择防御规则,DLI支持的系统防御规则请参考DLI支持的SQL防御系统规则。
队列
选择绑定规则的队列。
描述信息
输入规则描述信息。
防御规则动作
配置当前SQL防御规则动作的阈值参数。
SQL规则支持的类型:
- 提示:配置系统对SQL请求满足防御规则后是否进行日志记录和提示处理。开启按钮时,如果当前规则有变量参数,需同时配置阈值。
- 拦截:配置系统对SQL请求满足防御规则后是否进行拦截处理。开启按钮时,如果当前规则有变量参数,需同时配置阈值。
- 熔断:配置系统对SQL请求满足防御规则后是否进行熔断处理。开启按钮时,如果当前规则有变量参数,需同时配置阈值。
- 单击“确定”完成规则的添加。
规则添加成功后,可以在“SQL防御”界面查看已添加的防御规则。防御规则动态生效。
如需对当前规则进行调整,可单击对应规则所在“操作”列的“修改”,修改SQL防御规则。
DLI支持的SQL防御系统规则
本节操作介绍DLI支持的系统防御规则,详细信息参考表2。
- 系统默认创建的规则是指在队列创建时,DLI自动为您创建的SQL防御规则,该规则与队列绑定,且不支持删除。
- 以下规则为系统默认创建的规则:Scan files number、Scan partitions number、Shuffle data(GB)、Count(distinct) occurrences、Not in<Subquery>
- 同一个队列,同一个动作的防御规则仅支持创建一条。
- 系统默认创建的规则会分别创建每个支持动作的规则。例如:创建队列时,会分别创建“提示”和“拦截”动作的Scan files number规则。
- 不同的引擎版本支持的防御规则不同。
如需查看队列的引擎版本,您可以在队列资源的资源列表页面,通过查看队列基本信息中的“默认版本”获取引擎的版本信息。
图1 查看队列引擎版本
规则ID | 规则名称 | 说明 | 类别 | 适用引擎 | 支持的动作 | 取值说明 | 系统默认创建规则 | SQL语句示例 | 支持的引擎版本 |
|---|---|---|---|---|---|---|---|---|---|
dynamic_0001 | Scan files number | 扫描文件数的限制。 | dynamic | spark | 提示 拦截 | 取值范围:1-2000000 默认值:200000 | 是 | NA | Spark 3.3.1 |
dynamic_0002 | Scan partitions number | 对单个表操作(select,delete,update,alter)涉及的分区数超限制。 | dynamic | spark | 提示 拦截 | 取值范围:1-500000 默认值:5000 | 是 | select * from 分区表 | Spark 3.3.1 |
running_0002 | Memory used(MB) | SQL的占用内存峰值超绝对值限制。 | running | spark | 熔断 | 取值范围:1-8388608 | 否 | NA | Spark 3.3.1 |
running_0003 | Run time(S) | SQL已经运行的时长限制。 | running | spark | 熔断 | 单位:秒 取值范围:1-43200 | 否 | NA | Spark 3.3.1 |
running_0004 | Scan data(GB) | 扫描数据量的限制。 | running | spark | 熔断 | 单位:GB 取值范围:1-10240 | 否 | NA | Spark 3.3.1 |
running_0005 | Shuffle data(GB) | Shuffle数据量的限制。 | running | spark | 熔断 | 单位:GB 取值范围:1-10240 默认值:2048 | 是 | NA | Spark 3.3.1 Spark 2.4.5 |
static_0001 | Count(distinct) occurrences | SQL中count(distinct)出现次数限制。 | static | spark | 提示 拦截 | 取值范围:1-100 默认值:10 | 是 | SELECT COUNT(DISTINCT deviceId), COUNT(DISTINCT collDeviceId) FROM table GROUP BY deviceName, collDeviceName, collCurrentVersion; | Spark 3.3.1 |
static_0002 | Not in<Subquery> | SQL中是否使用了not in <subquery>语句。 | static | spark | 提示 拦截 | 取值范围:是/否 默认值:是 | 是 | SELECT * FROM Orders o WHERE Orders.Order_ID not in (Select Order_ID FROM HeldOrders h where h.order_id =o.order_id); | Spark 3.3.1 |
static_0003 | Join occurrences | SQL中的join次数的限制。 | static | spark | 提示 拦截 | 取值范围:1-50 | 否 | SELECT name, text FROM table_1 JOIN table_2 ON table_1.Id =table_2.Id | Spark 3.3.1 |
static_0004 | Union occurrences | SQL中的union all次数的限制。 | static | spark | 提示 拦截 | 取值范围:1-100 | 否 | select * from tables t1 union all select * from tables t2 union all select * from tables t3 | Spark 3.3.1 |
static_0005 | Subquery nesting layers | 子查询嵌套层数的限制。 | static | spark | 提示 拦截 | 取值范围:1-20 | 否 | select * from ( with temp1 as (select * from tables) select * from temp1); | Spark 3.3.1 |
static_0006 | Sql size(KB) | SQL文件大小的限制。 | static | spark | 提示 拦截 | 单位:KB 取值范围:1-1024 | 否 | NA | Spark 3.3.1 |
static_0007 | Cartesian product | 多表关联时笛卡尔积的限制 | static | spark | 提示 拦截 | 取值范围:0-1 | 否 | select * from A,B; | Spark 3.3.1 |

