# 使用rds_pg_sql_ccl插件
#### 简介
高并发和消耗资源过多的SQL会导致实例不稳定，对此，TaurusDB for PostgreSQL提供了限流能力，是由华为云自研插件rds_pg_sql_ccl实现，其中ccl是concurrent control的缩写，合理地使用SQL限流可以保障实例的稳定性，可以很好地做到性能优化和资源保护，应对的场景有：
- 业务量突增：通过限制某类SQL的执行保障实例的稳定性。
- 保障核心任务：通过限制其他SQL的执行从而降低资源的消耗保障核心任务的顺利完成。
该插件提供了两种限流方式：
- 方式1： 限制同一时刻同时执行SQL数量（ 由rds_pg_sql_ccl.max_concurrent_sql参数控制，默认值为-1，即不限制）。
- 方式2： 限制某一类SQL（query id相同）同一时刻并发执行的数量，由限流规则控制，限流规则见下文。
 
TaurusDB for PostgreSQL实例支持的插件，具体可参见[支持的插件列表](https://support.huaweicloud.com/usermanual-taurusdb-pg/taurusdb_03_0081.html)。
#### 使用说明
一定要根据业务和资源使用的实际情况合理配置SQL限流规则，否则可能会影响业务。
#### 创建规则
1. 同一个数据库中，不能创建重复（query id相同）的限流规则；不同的数据库中，可以创建重复的限流规则。
2. 规则创建后不会立刻生效，需要调用enable_ccl_rule函数让规则生效。
3. get_query_id函数获取不到绑定变量的SQL的queryid，add_ccl_rule_by_query限制不了绑定变量SQL。
4. 绑定变量SQL的queryid可以通过pg_stat_statements插件获取，之后可以通过add_ccl_rule_by_queryid创建规则，可参考后续绑定变量SQL限流。
 
#### 规则生效
1. 方式1限制了同一时刻并发执行SQL数量，该规则会优先生效。在方式1的基础上还可以进一步通过方式2，限制某类特定SQL的并发执行。
2. 数据库重启后，所有规则不再生效。
3. 限流规则只对后续执行的SQL生效，已经并发执行的SQL不受影响。
 
#### 绑定变量的SQL限流
JDBC等驱动支持prepare statement，对参数化SQL进行预编译，在输入参数后实际执行SQL。在pg_stat_statements视图中会以绑定变量的方式呈现。对于参数是绑定变量的SQL，内核计算的query id值与参数为实际值的SQL不一致，因此无法直接通过添加SQL语句方式进行限流。
对于这类SQL而言，只能通过实际执行后手动添加的方式进行限流。
1. 首先实际执行一次带绑定变量的SQL，这样内核会计算其query id。基于JDBC的prepare statement程序示例如下：
   ```
   String sql = "select pg_sleep(?);";
   PreparedStatement preparedStatement = conn.prepareStatement(sql);
   preparedStatement.setInt(1, 500);
   ResultSet resultSet = preparedStatement.executeQuery();
   ```
   
2. 而后在pg_stat_statements视图可以查询到该SQL的query id。
   ```
   select queryid from pg_stat_statements where query like '%select pg_sleep%';
   ```
   
3. 通过查询到的query id添加限流规则。
   ```
   select rds_pg_sql_ccl.add_ccl_rule_by_queryid($queryid);
   ```
   
4. 通过上一条SQL的返回值(rule_id)使该规则生效。
   ```
   select rds_pg_sql_ccl.enable_ccl_rule($rule_id);
   ```
   
5. 从插件提供的get_all_enabled_rule视图可以获取到当前所有生效的限流规则。
   ```
   select * from rds_pg_sql_ccl.get_all_enabled_rule;
   ```
   
 
#### 参数说明
表1参数说明 
| 参数名                                  | 数据类型 | 默认值   | 最大值     | 最小值  | 含义                              |
|:---|:---|:---|:---|:---|:---|
| rds_pg_sql_ccl.enable_ccl           | bool    | false | -      | - | 是否开启限流规则。                       |
| rds_pg_sql_ccl.max_enabled_rules   | int  | 5000 | 500000   | 0  | 同时生效的限流规则数。                      |
| rds_pg_sql_ccl.max_concurrent_sql | int  | -1     | 50000 | -1 | 并发执行的SQL数量（优先级高于限流规则），\<0是不限制。 |
   
#### 函数接口说明
表2函数接口说明 
| 函数名                                      | 参数                                                                                                                                                                                                                                                                                                                                                    | 返回值       | 功能                 |
|:---|:---|:---|:---|
| rds_pg_sql_ccl.get_query_id               | query_string text, search_path text default 'public'                                                                                                                                                                                                                     | queryid | 计算SQL的queryid。  |
| rds_pg_sql_ccl.add_ccl_rule_by_query    | query_string text, max_concurrency int default 0, max_waiting int default 0, search_path text default 'public' | ruleid   | 通过SQL语句添加限流规则。  |
| rds_pg_sql_ccl.add_ccl_rule_by_queryid | query_id bigint, max_concurrency int default 0, max_waiting int default 0, search_path text default 'public'       | ruleid   | 通过queryid添加限流规则。 |
| rds_pg_sql_ccl.enable_ccl_rule         | rule_id bigint                                                                                                                                                                                                                                                                                                                                         | bool     | 通过ruleid让限流规则生效。 |
| rds_pg_sql_ccl.disable_ccl_rule          | rule_id bigint                                                                                                                                                                                                                                                                                                                                      | bool    | 通过ruleid让限流规则失效。  |
| rds_pg_sql_ccl.disable_all_ccl_rule      | -                                                                                                                                                                                                                                                                                                                                                    | void     | 让所有限流规则失效。      |
| rds_pg_sql_ccl.delete_ccl_rule           | rule_id bigint                                                                                                                                                                                                                                                                                                                                      | void     | 通过ruleid删除限流规则。  |
| rds_pg_sql_ccl.update_ccl_rule           | new_rule_id bigint, new_max_concurrency int, new_max_waiting int                                                                                                                              | void      | 通过ruleid更新限流规则。    |
   
部分参数说明：
- max_concurrency：最大并发数，并发执行该类型SQL的最大数量。
- max_wait：最大等待时间，达到最大并发数之后，该类型的新SQL的最大等待时间，超过这个时间，则执行失败。
- new_max_concurrency：新的最大并发数。
- new_max_wait：新的最大等待时间。
 
#### 视图接口说明
表3视图接口说明 
| 序号 | 视图                                        | 列                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                             | 说明                               |
|:---|:---|:---|:---|
| 1   | rds_pg_sql_ccl.get_all_enabled_rule       | dbid oid, queryid bigint, max_concurrency int, max_wait int                                                                                                                                                                                                                                                                                                                                                                                                  | 查看所有生效的限流规则。                   |
| 2  | rds_pg_sql_ccl.get_activity_query_status | queryid bigint, wait_start_time timestamptz, pid int, dbid oid                                                                                                                                                                                                                                                                                                                                                                                             | 查看当前实例每个SQL的运行状态（queryid，是否等待等）。 |
| 3    | rds_pg_sql_ccl.get_current_db_ccl_rule   | rule_id bigint, query_id bigint , query_string, max_concurrency int, max_waiting int, search_path text, create_time timestamptz, enabled bool | 查看当前数据库创建的限流规则（不一定生效）。           |
   
