
# 配置Hive自读自写SQL防御规则
#### 操作场景
Hive支持对自读自写的SQL语句进行拦截。如果一条SQL语句中查询的表、分区或目录与插入的表、分区或目录一致，且以覆盖的方式插入查询的结果数据，便可判定存在自读自写的场景，用户可以在SQL防御界面通过添加规则ID为"dynamic_0004"的防御规则开启该拦截功能。
Hive自读自写的SQL样例如下：
- 非分区表： **INSERT OVERWRITE TABLE** *tbl_a* **SELECT \* FROM** *tbl_a* **;**
  
- 静态分区表： **INSERT OVERWRITE TABLE** *tbl_b* **PARTITION (ds='20240101') SELECT \* FROM** *tbl_b* **WHERE ds='20240101';**
  
- 动态分区： **INSERT OVERWRITE TABLE** *tbl_c* **PARTITION(pday) SELECT id,name,pday FROM** *tbl_c* **WHERE id \> 100;**
  
- 写入数据到HDFS的表中： **INSERT OVERWRITE DIRECTORY** **'hdfs://** *hacluster/user/hive/warehouse/tbl_d* **' SELECT \* FROM** *tbl_d* **;**
  
 
#### 约束与限制
该章节仅适用于MRS 3.5.0及之后版本。
#### 操作步骤
1. 使用具有Manager界面管理权限的用户登录FusionInsight Manager。
2. 选择"集群 \> SQL防御"，单击"添加规则"，输入当前用户密码并单击"确定"，进入添加规则界面。
3. 在添加规则界面配置以下参数并单击"确定"： 
   - 规则名称：输入SQL防御规则名称，例如：test。
   
   - 规则ID：选择"dynamic_0004"。
   
   - 租户：单击"添加"选择可适用当前防御规则的租户名称，例如：default。
   
   - 服务与动作：单击"添加"，在添加服务与动作页面配置以下参数并单击"确定"：
     - 服务：选择"Hive"。
     
     - 根据业务实际需求开启"提示"或"拦截"按钮。
      
   
   
   图1创建Hive SQL防御规则   
   ![](https://support.huaweicloud.com/cmpntguide-lts-mrs/zh-cn_image_0000002096943773.png "点击放大")
   
   
4. 登录安装有Hive客户端的节点，执行以下命令，切换到客户端安装目录。 
   ```
   cd 客户端安装目录
   ```
   执行以下命令，配置环境变量。
   ```
   source bigdata_env
   ```
   执行以下命令认证当前用户（若集群未启用Kerberos认证（普通模式）请跳过该操作）：
   ```
   kinit 具有Hive操作权限的组件业务用户
   ```
   
   
5. 执行以下命令登录Hive客户端： 
   ```
   beeline
   ```
   
   
6. 执行以下命令创建一个表并插入数据： 
   删除表：
   ```
   drop table tbl_a;
   ```
   创建表：
   ```
   create table tbl_a(id int, name string);
   ```
   向表中插入数据：
   ```
   insert into table tbl_a values(123,'sjk'),(234,'shen'),(111,'aaa');
   ```
   
   
7. （可选）在SQL防御中配置了自读自写拦截规则后，对于涉及动态分区场景默认情况下是按照nonstrict模式拦截的，如果需要按照分区精准拦截，可执行以下命令进行设置，参数介绍请参见[设置Hive动态分区表精准拦截]：
   
   ```
   set hive-ext.dynamic.partition.intercept.mode=strict;
   ```
   
   
8. 执行以下SQL语句命令，检查当前SQL防御规则是否生效。 
   ```
   insert overwrite table tbl_a select * from tbl_a;
   ```
   若配置的动作为"提示"，当系统识别到SQL语句满足防御规则后，系统会打印告警信息，SQL任务继续运行，提示信息如下：
   ```
   WARN  : DYNAMIC_0004 Self-read and self-overwrite operations are not allowed.
   ```
   若配置的动作为"拦截"，当系统识别到SQL语句满足防御规则后，SQL任务将被拦截，不会继续运行，系统回显信息如下：
   ```
   Error: Error while compiling statement: FAILED: RuleException DYNAMIC_0004 Self-read and self-overwrite operations are not allowed. (state=42000,code=40000)
   ```
   
   
 
 #### 设置Hive动态分区表精准拦截
针对涉及动态分区的自读自写场景，由于动态分区在编译阶段获取不到输出的分区信息，无法判断是否存在自读自写场景，为了实现拦截功能，提供了nonstrict和strict两种拦截模式供用户选择。其中：
- nonstrict模式是按照表进行拦截的，即对提交的SQL任务判断是否存在查询的表和写入的表是同一张表，如果存在就进行拦截，否则不拦截。nonstrict模式的拦截逻辑是在SQL编译阶段完成的，该模式优点是拦截效率高，缺点是查询和写入分区所对应的表相同，分区不同时也会被拦截。
- strict模式是按照分区进行拦截的，即对提交的SQL任务判断是否存在查询的分区和写入的分区相同，如果存在就进行拦截，否则不拦截。strict模式的拦截逻辑是在SQL任务执行MoveTask阶段完成的，该模式优点是拦截精度高，缺点是拦截成本高，因为需要等到SQL任务大部分逻辑运行完且运行到MoveTask阶段才识别是否需要进行拦截。
 
在SQL防御中配置了自读自写拦截规则，对于涉及动态分区场景默认情况下是按照nonstrict模式拦截的，如果需要按照分区精准拦截，还需要将[表1]的"hive-ext.lakeformation.transform.role"参数的值设置为"strict"。该参数值建议对单个任务进行设置，例如执行SQL语句**set hive-ext.dynamic.partition.intercept.mode=strict;**，不建议全局配置。
 表1参数说明 
| 参数名称                                      | 默认值       | 参数描述                                                                                                                                                                                                                                                                                                                                     |
|:---|:---|:---|
| hive-ext.dynamic.partition.intercept.mode | nonstrict | 设置Hive动态分区表自读自写的拦截方式，包括： - nonstrict：按照表进行拦截，即一条SQL语句中查询的表和插入的表数据存在相同的表便会被拦截。  - strict：按照分区拦截，即一条SQL语句中查询的分区和插入的分区数据存在相同的分区便会被拦截。   |
   
