更新时间:2024-10-24 GMT+08:00

使用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限流规则,否则可能会影响业务。

创建规则

  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. 只读会同步主库的规则,然后调用enable_ccl_rule函数让规则生效。
  4. 限流规则只对后续执行的SQL生效,已经并发执行的SQL不受影响。

非绑定变量的SQL限流

前置条件:

  1. 开启限流规则需要先安装内核插件rds_pg_sql_ccl,可以通过界面安装,也可执行SQL安装。
    SELECT control_extension ('create', 'rds_pg_sql_ccl');
  2. 设置内核参数。
    rds_pg_sql_ccl.enable_ccl = on

而后,依次进行如下操作:

  1. 在实例管理页面,单击实例名称,进入概览页。
  2. 在左侧导航栏,选择“智能DBA助手 > 历史诊断”。
  3. 选择“全量SQL > SQL限流”。
  4. 打开SQL限流开关。
  5. 单击“新建SQL限流规则”,配置SQL限流规则参数。
    图1 新建限流规则
    • 单击“启用”,即可开启限流规则。
      图2 启动规则
    • 单击“停用”,即可停用限流规则。
      图3 停用规则
    • 单击“删除”,即可删除限流规则,删除启用状态下的限流规则,该规则不会继续生效。
      图4 删除规则

绑定变量的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 函数接口说明

序号

函数名

参数

返回值

功能

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:新的最大等待时间。

视图接口说明

表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

查看当前数据库创建的限流规则(不一定生效)。