达梦数据库-学习-10-SQL 注入 HINT 规则(固定执行计划)

目录

一、环境信息

二、简述

三、参数介绍

四、存过介绍

1、SF_INJECT_HINT

(1)声明

(2)存过说明

(3)注意

(4)参数含义

(5)返回值

2、SF_ALTER_HINT

(1)声明

(2)存过说明

(3)注意

(4)参数含义

(5)返回值

3、SF_DEINJECT_HINT

(1)声明

(2)存过说明

(3)注意

(4)参数含义

(5)返回值

五、视图介绍

1、SYSINJECTHINT

六、虚机实验

1、开启参数

2、测试SQL

3、注入HINT

4、查看视图

5、验证SQL

6、设置当前会话不生效

7、查看视图

8、测试SQL

9、会话级修改参数SQLTUNE_CATEGORY

10、验证SQL

11、删除注入HINT

12、验证是否删除


一、环境信息

|------|------------------------------------------------------------------------------------------------------------------------------|
| 名称 | 值 |
| CPU | 12th Gen Intel(R) Core(TM) i7-12700H |
| 操作系统 | CentOS Linux release 7.9.2009 (Core) |
| 内存 | 2G |
| 逻辑核数 | 2 |
| DM版本 | 1 DM Database Server 64 V8 2 DB Version: 0x7000c 3 03134284194-20240703-234060-20108 4 Msg Version: 12 5 Gsu level(5) cnt: 0 |

二、简述

在客户现场我们经常遇到生产环境慢SQL的问题,生产环境不可改应用(把等价改写和的路子堵死了),加索引计划中不走,指定HINT后计划变优,但不可改应用,所以这个方法也被毙掉了。SQL 注入 HINT 规则的优势就来了,可以在不修改SQL的情况下,注入HINT来影响执行计划。

三、参数介绍

|--------------------|---------|--------|-------------------------------------------------------------------------------------------------------------|
| 参数名 | 默认值 | 级别 | 描述 |
| ENABLE_INJECT_HINT | 0 | 动态会 话级 | 是否启用 SQL 指定 HINT 的功能。 0:不启用; 1:启用; |
| SQLTUNE_CATEGORY | DEFAULT | 动态会话级 | 限制本会话中被允许使用的 SQL 配置(包括为 SQL 注入的 HINT 规则)的生效类别。 当 SQL 配置存在生效类别限制且和本会话的 SQLTUNE_CATEGORY 不一致时,该 SQL 配置在本会话不生效 |

四、存过介绍

1、SF_INJECT_HINT

(1)声明

sql 复制代码
VARCHAR
SF_INJECT_HINT (
sql_text text,
hint_text text,
name varchar(128),
description varchar(256),
validate boolean,
fuzzy boolean,
need_clear boolean
)

(2)存过说明

为 SQL 注入 HINT 规则。

(3)注意

SF_INJECT_HINT 方法创建的 HINT 规则无生效类别限制,如果需要为该 HINT 规则设置生效类别,可通过 SF_ALTER_HINT 过程修改实现。

(4)参数含义

|-------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 参数名 | 含义 |
| sql_text | 待注入 HINT 规则的 SQL 语句。 |
| hint_text | 待注入的 HINT 规则,必须指定为非 NULL 值。 |
| name | HINT 规则的名称,指定为 NULL 值时系统为其命名。 |
| description | 对 HINT 规则的详细描述。 |
| validate | HINT 规则是否生效。TRUE 是;FALSE 否。 |
| fuzzy | 指定 SQL 的匹配规则为精准匹配或模糊匹配。 值为 TRUE 或 NULL时,为模糊匹配; 值为 FALSE 时,为精准匹配。 精准匹配时,待注入 HINT 规则的 SQL 语句 必 须 为 语 法 正 确 的 INSERT/DELETE/UPDATE/SELECT/MERGE INTO 语 句 ( 语 句 以EXPLAIN/EXPLAIN FOR 开头时,去掉 EXPLAIN/EXPLAIN FOR 后的语句必须完全正确),精准匹配要求 SQL 语句完全匹配,不支持 SQL 语句中的子查询匹配; 模糊匹配时,待注入 HINT规则的 SQL 语句应为非 NULL 值。 |
| need_clear | 是否同步清空所有缓存的计划。 值为 TRUE 或 NULL 时,清空缓存的计划; 值为 FALSE 时,不清空缓存的计划,需要手动清除对应 SQL 的 计划,指定的 hint 才能生效。 |

(5)返回值

执行成功返回名称,执行失败报错误信息。

2、SF_ALTER_HINT

(1)声明

sql 复制代码
INT 
SF_ALTER_HINT ( 
name varchar(128),
attribute_name varchar(12),
attribute_value varchar(256),
need_clear boolean 
)

(2)存过说明

修改 HINT 规则的属性。

(3)注意

无。

(4)参数含义

|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| 参数名 | 含义 |
| name | 要修改的规则名称,必须指定为非 NULL 值。 |
| attribute_name | 要修改的属性名,必须指定为非 NULL 值。 支持的可修改的属性名和属性值包括: 属性名 NAME,属性值为修改后的规则名; 属性名 DESCRIPTION,属性值为修改后的规则描述; 属性名 STATUS,属性值为 ENABLED/DISABLED; 属性名 CATEGORY,属性值为修改后的 HINT 的生效类别(由于 SF_INJECT_HINT 方法仅能注入无类别限制的 HINT,若需要注入带生效类别的 HINT,则还需要再调用一次 SF_ALTER_HINT 更改其生效类别)。 |
| attribute_value | 设置的属性值,必须指定为非 NULL 值。 |
| need_clear | 是否同步清空所有缓存的计划。 值为 TRUE 或 NULL 时,清空缓存的计划; 值为 FALSE 时,不清空缓存的计划,需要手动清除对应 SQL 的计划,否则 SQL 仍使用老计划。 |

(5)返回值

执行成功返回 0 ,执行失败返回错误码。

3、SF_DEINJECT_HINT

(1)声明

sql 复制代码
INT 
SF_DEINJECT_HINT ( 
name varchar(128),
need_clear boolean 
)

(2)存过说明

删除 SQL 中已注入的 HINT 规则。

(3)注意

无。

(4)参数含义

|------------|----------------------------------------------------------------------------------------------|
| 参数名 | 含义 |
| name | 要删除的规则名称,必须指定为非 NULL 值。 |
| need_clear | 是否同步清空所有缓存的计划。 值为 TRUE 或 NULL 时,清空缓存的计划; 值为 FALSE 时,不清空缓存的计划,需要手动清除对应 SQL 的计划,否则 SQL 仍使用老计划。 |

(5)返回值

执行成功返回 0 ,执行失败返回错误码。

五、视图介绍

1、SYSINJECTHINT

sql 复制代码
SQL> DESC SYSINJECTHINT;

行号     NAME        TYPE$           NULLABLE
---------- ----------- --------------- --------
1          NAME        VARCHAR(128)    N
2          DESCRIPTION VARCHAR(256)    Y
3          VALIDATE    VARCHAR(5)      Y
4          SQL_TEXT    TEXT            N
5          HINT_TEXT   TEXT            N
6          CREATOR     VARCHAR(128)    Y
7          CRTDATE     DATETIME(6)     Y
8          INFO1       INTEGER         Y
9          INFO2       VARBINARY(128)  Y
10         INFO3       VARBINARY(1024) Y

10 rows got

已用时间: 13.896(毫秒). 执行号:1018.

|-------------|--------------------------------------------------|
| 字段名 | 描述 |
| NAME | 规则名称 |
| DESCRIPTION | 规则的详细描述 |
| VALIDATE | 规则是否生效,取值 TRUE/FALSE |
| SQL_TEXT | 规则中的 SQL 语句 |
| HINT_TEXT | 为 SQL 语句注入的 HINT 规则内容 |
| CREATOR | 规则创建人 |
| CRTDATE | 规则创建时间 |
| INFO1 | 是否为模糊匹配。1 是;0 否,精确匹配 |
| INFO2 | HINT 规则的生效类别。可使用 BINTOCHAR函数将该字段转换为 VARCHAR 类型显示 |
| INFO3 | 保留字段 |

六、虚机实验

1、开启参数

sql 复制代码
SQL> CALL SP_SET_PARA_VALUE(1,'ENABLE_INJECT_HINT',1);
DMSQL 过程已成功完成
已用时间: 12.612(毫秒). 执行号:2003.

SQL> SELECT * FROM V$DM_INI WHERE PARA_NAME = 'ENABLE_INJECT_HINT';

行号     PARA_NAME          PARA_VALUE MIN_VALUE MAX_VALUE DEFAULT_VALUE MPP_CHK SESS_VALUE FILE_VALUE DESCRIPTION        PARA_TYPE SYNC_FLAG
---------- ------------------ ---------- --------- --------- ------------- ------- ---------- ---------- ------------------ --------- ---------
           SYNC_LEVEL
           ----------
1          ENABLE_INJECT_HINT 1          0         1         0             N       1          1          enable inject hint SESSION   ALL_SYNC
           CAN_SYNC


已用时间: 7.387(毫秒). 执行号:2004.

2、测试SQL

sql 复制代码
SQL> EXPLAIN SELECT * FROM ZXJ.TEST T1 JOIN ZXJ.TEST T2 ON T1.A = T2.A;

1   #NSET2: [4, 29405, 8] 
2     #PRJT2: [4, 29405, 8]; exp_num(2), is_atom(FALSE) 
3       #HASH2 INNER JOIN: [4, 29405, 8];  KEY_NUM(1); KEY(T1.A=T2.A) KEY_NULL_EQU(0)
4         #CSCN2: [1, 10000, 4]; INDEX33555476(TEST as T1); btr_scan(1)
5         #CSCN2: [1, 10000, 4]; INDEX33555476(TEST as T2); btr_scan(1)

已用时间: 0.829(毫秒). 执行号:0.

我们可以才看出,在没有干预的情况下,优化器选的是哈希内连接。

3、注入HINT

sql 复制代码
SQL> CALL 
SF_INJECT_HINT (
'SELECT * FROM ZXJ.TEST T1 JOIN ZXJ.TEST T2 ON T1.A = T2.A;',
'USE_NL(T1,T2)',
NULL,
'',
TRUE,
FALSE,
TRUE
);2   3   4   5   6   7   8   9   10  
DMSQL 过程已成功完成
已用时间: 19.472(毫秒). 执行号:2006.

4、查看视图

sql 复制代码
SQL> SELECT * FROM SYSINJECTHINT;

行号     NAME                         DESCRIPTION VALIDATE SQL_TEXT                                                   HINT_TEXT     CREATOR
---------- ---------------------------- ----------- -------- ---------------------------------------------------------- ------------- -------
           CRTDATE                    INFO1       INFO2      INFO3     
           -------------------------- ----------- ---------- ----------
1          INJECT_HINT_ad9ccfdb7ec1745f             TRUE     SELECT * FROM ZXJ.TEST T1 JOIN ZXJ.TEST T2 ON T1.A = T2.A; USE_NL(T1,T2) SYSDBA
           2025-02-14 17:28:19.701426 0           NULL       NULL


已用时间: 3.337(毫秒). 执行号:2007.

5、验证SQL

sql 复制代码
SQL> EXPLAIN SELECT * FROM ZXJ.TEST T1 JOIN ZXJ.TEST T2 ON T1.A = T2.A;

1   #NSET2: [17551877, 29405, 8] 
2     #PRJT2: [17551877, 29405, 8]; exp_num(2), is_atom(FALSE) 
3       #SLCT2: [17551877, 29405, 8]; T1.A = T2.A
4         #NEST LOOP INNER JOIN2: [17551877, 29405, 8] 
5           #CSCN2: [1, 10000, 4]; INDEX33555476(TEST as T1); btr_scan(1)
6           #CSCN2: [1, 10000, 4]; INDEX33555476(TEST as T2); btr_scan(1)

已用时间: 0.809(毫秒). 执行号:0.

我们可以发现计划中两表的连接方式变为了嵌套循环连接,说明我们的SQL注入HINT配置成功。

6、设置当前会话不生效

sql 复制代码
CALL 
SF_ALTER_HINT ( 
'INJECT_HINT_ad9ccfdb7ec1745f',
'CATEGORY',
'SUN',
TRUE 
);

7、查看视图

sql 复制代码
SQL> SELECT NAME,DESCRIPTION,"VALIDATE",SQL_TEXT,HINT_TEXT,CREATOR,CRTDATE,INFO1,BINTOCHAR(INFO2) FROM SYSINJECTHINT;

行号     NAME                         DESCRIPTION VALIDATE SQL_TEXT                                                   HINT_TEXT     CREATOR
---------- ---------------------------- ----------- -------- ---------------------------------------------------------- ------------- -------
           CRTDATE                    INFO1       BINTOCHAR(INFO2)
           -------------------------- ----------- ----------------
1          INJECT_HINT_ad9ccfdb7ec1745f             TRUE     SELECT * FROM ZXJ.TEST T1 JOIN ZXJ.TEST T2 ON T1.A = T2.A; USE_NL(T1,T2) SYSDBA
           2025-02-14 17:28:19.701426 0           SUN


已用时间: 6.296(毫秒). 执行号:2010.

8、测试SQL

sql 复制代码
SQL> EXPLAIN SELECT * FROM ZXJ.TEST T1 JOIN ZXJ.TEST T2 ON T1.A = T2.A;

1   #NSET2: [4, 29405, 8] 
2     #PRJT2: [4, 29405, 8]; exp_num(2), is_atom(FALSE) 
3       #HASH2 INNER JOIN: [4, 29405, 8];  KEY_NUM(1); KEY(T1.A=T2.A) KEY_NULL_EQU(0)
4         #CSCN2: [1, 10000, 4]; INDEX33555476(TEST as T1); btr_scan(1)
5         #CSCN2: [1, 10000, 4]; INDEX33555476(TEST as T2); btr_scan(1)

已用时间: 0.868(毫秒). 执行号:0.

SQL> SELECT * FROM V$DM_INI WHERE PARA_NAME = 'SQLTUNE_CATEGORY';

行号     PARA_NAME        PARA_VALUE MIN_VALUE MAX_VALUE DEFAULT_VALUE MPP_CHK SESS_VALUE FILE_VALUE
---------- ---------------- ---------- --------- --------- ------------- ------- ---------- ----------
           DESCRIPTION                                                  PARA_TYPE SYNC_FLAG SYNC_LEVEL
           ------------------------------------------------------------ --------- --------- ----------
1          SQLTUNE_CATEGORY DEFAULT    NULL      NULL      NULL          N       DEFAULT    DEFAULT
           The category of SQL profiles that take effect in the session SESSION   ALL_SYNC  CAN_SYNC


已用时间: 8.464(毫秒). 执行号:2011.

由于本会话的参数SQLTUNE_CATEGORY的值DEFAULT与设置的值SUN不一致,所以此SQL注入HINT不生效。

9、会话级修改参数SQLTUNE_CATEGORY

sql 复制代码
SQL> CALL SF_SET_SESSION_PARA_VALUE('SQLTUNE_CATEGORY','SUN');
DMSQL 过程已成功完成
已用时间: 2.563(毫秒). 执行号:2012.

SQL> SELECT * FROM V$DM_INI WHERE PARA_NAME = 'SQLTUNE_CATEGORY';

行号     PARA_NAME        PARA_VALUE MIN_VALUE MAX_VALUE DEFAULT_VALUE MPP_CHK SESS_VALUE FILE_VALUE
---------- ---------------- ---------- --------- --------- ------------- ------- ---------- ----------
           DESCRIPTION                                                  PARA_TYPE SYNC_FLAG SYNC_LEVEL
           ------------------------------------------------------------ --------- --------- ----------
1          SQLTUNE_CATEGORY DEFAULT    NULL      NULL      NULL          N       SUN        DEFAULT
           The category of SQL profiles that take effect in the session SESSION   ALL_SYNC  CAN_SYNC


已用时间: 7.108(毫秒). 执行号:2013.

这次参数SQLTUNE_CATEGORY的会话值SUN与设置的值SUN不一致了。

10、验证SQL

sql 复制代码
SQL> EXPLAIN SELECT * FROM ZXJ.TEST T1 JOIN ZXJ.TEST T2 ON T1.A = T2.A;

1   #NSET2: [17551877, 29405, 8] 
2     #PRJT2: [17551877, 29405, 8]; exp_num(2), is_atom(FALSE) 
3       #SLCT2: [17551877, 29405, 8]; T1.A = T2.A
4         #NEST LOOP INNER JOIN2: [17551877, 29405, 8] 
5           #CSCN2: [1, 10000, 4]; INDEX33555476(TEST as T1); btr_scan(1)
6           #CSCN2: [1, 10000, 4]; INDEX33555476(TEST as T2); btr_scan(1)

已用时间: 0.789(毫秒). 执行号:0.

又变回来了。

11、删除注入HINT

sql 复制代码
SQL> CALL 
SF_DEINJECT_HINT ( 
'INJECT_HINT_ad9ccfdb7ec1745f',
TRUE 
);2   3   4   5   
DMSQL 过程已成功完成
已用时间: 5.053(毫秒). 执行号:2014.

12、验证是否删除

sql 复制代码
SQL> EXPLAIN SELECT * FROM ZXJ.TEST T1 JOIN ZXJ.TEST T2 ON T1.A = T2.A;

1   #NSET2: [4, 29405, 8] 
2     #PRJT2: [4, 29405, 8]; exp_num(2), is_atom(FALSE) 
3       #HASH2 INNER JOIN: [4, 29405, 8];  KEY_NUM(1); KEY(T1.A=T2.A) KEY_NULL_EQU(0)
4         #CSCN2: [1, 10000, 4]; INDEX33555476(TEST as T1); btr_scan(1)
5         #CSCN2: [1, 10000, 4]; INDEX33555476(TEST as T2); btr_scan(1)

已用时间: 0.812(毫秒). 执行号:0.

SQL> SELECT NAME,DESCRIPTION,"VALIDATE",SQL_TEXT,HINT_TEXT,CREATOR,CRTDATE,INFO1,BINTOCHAR(INFO2) FROM SYSINJECTHINT;
未选定行

已用时间: 1.033(毫秒). 执行号:2015.

我们可以看出计划变回最先的了,系统视图中也看不到了。

相关推荐
慌糖8 分钟前
Ubuntu安装Docker命令清单(以20.04为例)
linux·ubuntu·docker
zhangzhiwei-zzw18 分钟前
Linux下使用nmcli连接网络
linux·网络·chrome
爱意随风起风止意难平1 小时前
003 flutter初始文件讲解(2)
学习·flutter
东京老树根1 小时前
SAP学习笔记 - 开发18 - 前端Fiori开发 应用描述符(manifest.json)的用途
笔记·学习
hgdlip1 小时前
电脑的ip地址会自动变怎么办?原因解析和解决方法
运维·网络·tcp/ip·电脑
ZZH1120KQ1 小时前
Linux账号和权限管理
linux·运维
heart000_11 小时前
MySQL事务与锁机制详解:确保数据一致性的关键【MySQL系列】
数据库·mysql
@Liu_GuoXing1 小时前
Registry和docker有什么关系?
运维·docker·容器·registry
一眼青苔1 小时前
MySQL 如何判断某个表中是否存在某个字段
数据库·mysql
虾球xz1 小时前
CppCon 2014 学习:C++ Memory Model Meets High-Update-Rate Data Structures
java·开发语言·c++·学习