使用rds_pg_sql_ccl插件
简介
高并发和消耗资源过多的SQL会导致实例不稳定,对此,RDS 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相同)同一时刻并发执行的数量,由限流规则控制,限流规则见下文。
支持的版本
PostgreSQL16.2, 15.4, 14.8, 13.11, 12.15, 11.20及以上的最新小版本支持该插件。可通过以下SQL语句查询当前实例是否支持该插件:
SELECT * FROM pg_available_extension_versions WHERE name = 'rds_pg_sql_ccl';
如果不支持,可通过升级内核小版本或者使用转储与还原升级大版本使用该插件。
RDS for PostgreSQL实例支持的插件,具体可参见支持的插件列表。
使用说明
一定要根据业务和资源使用的实际情况合理配置SQL限流规则,否则可能会影响业务。
创建规则
- 同一个数据库中,不能创建重复(query id相同)的限流规则;不同的数据库中,可以创建重复的限流规则。
- 规则创建后不会立刻生效,需要调用enable_ccl_rule函数让规则生效。
- get_query_id函数获取不到绑定变量的SQL的queryid,add_ccl_rule_by_query限制不了绑定变量SQL。
- 绑定变量SQL的queryid可以通过pg_stat_statements插件获取,之后可以通过add_ccl_rule_by_queryid创建规则,可参考后续绑定变量SQL限流。
规则生效
- 方式1限制了同一时刻并发执行SQL数量,该规则会优先生效。在方式1的基础上还可以进一步通过方式2,限制某类特定SQL的并发执行。
- 数据库重启后,所有规则不再生效。
- 只读会同步主库的规则,然后调用enable_ccl_rule函数让规则生效。
- 限流规则只对后续执行的SQL生效,已经并发执行的SQL不受影响。
非绑定变量的SQL限流
前置条件:
- 开启限流规则需要先安装内核插件rds_pg_sql_ccl,可以通过界面安装,也可执行SQL安装。
SELECT control_extension ('create', 'rds_pg_sql_ccl');
- 设置内核参数。
rds_pg_sql_ccl.enable_ccl = on
而后,依次进行如下操作:
- 在实例管理页面,单击实例名称,进入概览页。
- 在左侧导航栏,选择“智能DBA助手 > 历史诊断”。
- 选择“全量SQL > SQL限流”。
- 打开SQL限流开关。
- 单击“新建SQL限流规则”,配置SQL限流规则参数。
图1 新建限流规则
- 单击“启用”,即可开启限流规则。
图2 启动规则
- 单击“停用”,即可停用限流规则。
图3 停用规则
- 单击“删除”,即可删除限流规则,删除启用状态下的限流规则,该规则不会继续生效。
图4 删除规则
- 单击“启用”,即可开启限流规则。
绑定变量的SQL限流
JDBC等驱动支持prepare statement,对参数化SQL进行预编译,在输入参数后实际执行SQL。在pg_stat_statements视图中会以绑定变量的方式呈现。对于参数是绑定变量的SQL,内核计算的query id值与参数为实际值的SQL不一致,因此无法直接通过添加SQL语句方式进行限流。
对于这类SQL而言,只能通过实际执行后手动添加的方式进行限流。
- 首先实际执行一次带绑定变量的SQL,这样内核会计算其query id。基于JDBC的prepare statement程序示例如下:
String sql = "select pg_sleep(?);"; PreparedStatement preparedStatement = conn.prepareStatement(sql); preparedStatement.setInt(1, 500); ResultSet resultSet = preparedStatement.executeQuery();
- 而后在pg_stat_statements视图可以查询到该SQL的query id。
select queryid from pg_stat_statements where query like '%select pg_sleep%';
- 通过查询到的query id添加限流规则。
select rds_pg_sql_ccl.add_ccl_rule_by_queryid($queryid);
- 通过上一条SQL的返回值(rule_id)使该规则生效。
select rds_pg_sql_ccl.enable_ccl_rule($rule_id);
- 从插件提供的get_all_enabled_rule视图可以获取到当前所有生效的限流规则。
select * from rds_pg_sql_ccl.get_all_enabled_rule;
参数说明
参数名 |
数据类型 |
默认值 |
最大值 |
最小值 |
含义 |
---|---|---|---|---|---|
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是不限制。 |
函数接口说明
序号 |
函数名 |
参数 |
返回值 |
功能 |
---|---|---|---|---|
1 |
rds_pg_sql_ccl.get_query_id |
query_string text, search_path text default 'public' |
queryid |
计算SQL的queryid。 |
2 |
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语句添加限流规则。 |
3 |
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添加限流规则。 |
5 |
rds_pg_sql_ccl.enable_ccl_rule |
rule_id bigint |
bool |
通过ruleid让限流规则生效。 |
6 |
rds_pg_sql_ccl.disable_ccl_rule |
rule_id bigint |
bool |
通过ruleid让限流规则失效。 |
7 |
rds_pg_sql_ccl.disable_all_ccl_rule |
- |
void |
让所有限流规则失效。 |
8 |
rds_pg_sql_ccl.delete_ccl_rule |
rule_id bigint |
void |
通过ruleid删除限流规则。 |
9 |
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:新的最大等待时间。
视图接口说明
序号 |
视图 |
列 |
说明 |
---|---|---|---|
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 |
查看当前数据库创建的限流规则(不一定生效)。 |