
# 配置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请求进行提示、拦截或熔断操作。
![](https://support.huaweicloud.com/usermanual-dli/public_sys-resources/note_3.0-zh-cn.png)
添加或者修改SQL防御规则时请结合业务场景评估规则的开启、规则阈值是否合理，避免不合理的防御规则对相关SQL请求进行拦截或阻断后，对业务造成影响。
1. 登录DLI管理控制台。
2. 选择"全局配置 \> SQL防御"，打开SQL防御页面。
3. 单击"创建规则"，编辑规则信息。
   表1SQL防御规则参数配置 
   | 参数     | 说明                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                    |
   |:---|:---|
   | 规则名称   | 自定义SQL防御规则名称。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         |
   | 系统规则   | 选择防御规则，DLI支持的系统防御规则请参考[DLI支持的SQL防御系统规则]。                                                                                                                                                                                                                                                                                                                                                                                                                           |
   | 队列     | 选择绑定规则的队列。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                            |
   | 描述信息   | 输入规则描述信息。                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
   | 防御规则动作 | 配置当前SQL防御规则动作的阈值参数。 SQL规则支持的类型： - 提示：配置系统对SQL请求满足防御规则后是否进行日志记录和提示处理。开启按钮时，如果当前规则有变量参数，需同时配置阈值。  - 拦截：配置系统对SQL请求满足防御规则后是否进行拦截处理。开启按钮时，如果当前规则有变量参数，需同时配置阈值。  - 熔断：配置系统对SQL请求满足防御规则后是否进行熔断处理。开启按钮时，如果当前规则有变量参数，需同时配置阈值。   |
      
   
4. 单击"确定"完成规则的添加。 规则添加成功后，可以在"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查看队列引擎版本   
  ![](https://support.huaweicloud.com/usermanual-dli/zh-cn_image_0000002031160097.png "点击放大") 
 表2DLI支持的系统防御规则 
| 规则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                                           |
   
