为了确保MySQL实例在面对突发请求流量、高资源消耗语句和SQL访问模型变化时的稳定运行,阿里云提供了基于语句规则的并发控制(CCL)及相应的工具包(DBMS_CCL)。通过DBMS_CCL,您可以限制特定类型SQL语句的最大并行执行数量。当指定SQL的并行执行数达到设定的限额后,额外的SQL语句则会进入等待状态,直到SQL的并行数量小于设定的限额。
实例版本如下: MySQL 8.4 MySQL 8.0(内核小版本20190816或以上) MySQL 5.7(内核小版本20200630或以上) 参数 说明 ccl_max_waiting_count 命中同一条CCL规则的SQL中,最多能处于 ccl_wait_timeout 处于 CCL的操作不产生日志,所以CCL的操作只影响当前实例。例如主实例进行CCL操作,不会同步到备实例、只读实例或灾备实例。 CCL提供超时机制以应对DML导致事务锁死锁,等待中的线程也会响应事务超时和线程KILL操作以应对死锁。 CCL规则定义了如下四个维度的特征: SQL command:SQL命令类型,例如SELECT、UPDATE、INSERT、DELETE等。 Object:SQL命令操作的对象,例如TABLE、VIEW等。 keywords:SQL命令的关键字。 Template:SQL命令的模板。 AliSQL设计了一个系统表(concurrency_control)保存CCL规则,系统启动时会自动创建该表,无需您手动创建。这里提供表的创建语句供您参考: 参数 说明 Id CCL规则ID。 Type SQL command,即SQL命令类型。 Schema_name 数据库名。 Table_name 数据库内的表名。 Concurrency_count 并发数。当并发数设置为0,会拒绝所有匹配该规则的SQL执行并返回错误码 Keywords 关键字,多个关键字用英文分号(;)分隔。 State 本规则是否启用。 Ordered Keywords中多个关键字是否按顺序匹配。 Digest 根据SQL_template进行Hash计算得到的64字节的Hash字符串。 SQL_template SQL语句的模板。 为了便捷地管理CCL规则,AliSQL在DBMS_CCL中定义了四个本地存储规则。详细说明如下: 命令模板 示例代码 增加SQL命令规则:SELECT语句的并发数为10。 增加关键字规则:SELECT语句中出现关键字key1的并发数为20。 增加完整规则:test.t表且出现关键字key2的SELECT语句的并发数为20。 前提条件 增加模板规则时,实例版本需满足以下要求: MySQL 8.4 MySQL 8.0 (内核小版本20230630及以上) MySQL 5.7 (内核小版本20241231及以上) 命令模板 说明 Table_name无需填写。Template_sql不能为空并且只能填写一条SQL。 可以通过STATEMENT_DIGEST_TEXT内置函数查看SQL对应的SQL模板。 示例代码 增加模板规则,test数据库下,SQL模板为 说明 在匹配限流规则时,每条SQL语句只能匹配一条限流规则。 规则匹配的优先级顺序如下:模板规则 > 完整限流规则 > 关键字规则 > SQL命令规则。依次检查每个规则集,以确定是否存在匹配的限流规则。 命令模板 示例代码 删除规则ID为15的CCL规则。 说明 如果删除的规则不存在,系统会报相应的警告,您可以使用 命令模板 示例代码 关于MATCHED、RUNNING和 参数 说明 MATCHED 规则匹配成功次数。 RUNNING 此规则下正在并发执行的线程数。 WAITTING 此规则下正在等待执行的线程数。 命令模板 如果您直接操作了表concurrency_control修改规则,规则不能立即生效,您需要让规则重新生效。命令如下: 示例代码 测试规则 设计如下三条规则对应三个维度: 测试场景 使用sysbench进行测试,场景如下: 64 threads 4 tables select.lua 测试结果 查看规则并发数情况如下: 查看RUNNING列,符合预期的并行数量。前提条件
参数说明
Concurrency control waiting状态的SQL数量。超过此限制后,SQL将执行失败并返回错误码ERROR 7534 (HY000): Concurrency control waiting count exceed max waiting count。默认值为0,表示没有限制。Concurrency control waiting状态的SQL能够等待的最长时间。超过此限制后,SQL会继续执行,不再受CCL的限制。默认值为86400秒。注意事项
功能设计
创建CCL规则表
CREATE TABLE `concurrency_control` (
`Id` bigint NOT NULL AUTO_INCREMENT,
`Type` enum('SELECT','UPDATE','INSERT','DELETE','TEMPLATE') CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT 'SELECT',
`Schema_name` varchar(64) COLLATE utf8mb3_bin DEFAULT NULL,
`Table_name` varchar(64) COLLATE utf8mb3_bin DEFAULT NULL,
`Concurrency_count` bigint NOT NULL,
`Keywords` text COLLATE utf8mb3_bin,
`State` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT 'Y',
`Ordered` enum('N','Y') CHARACTER SET utf8mb3 COLLATE utf8mb3_general_ci NOT NULL DEFAULT 'N',
`Digest` varchar(64) COLLATE utf8mb3_bin DEFAULT NULL,
`SQL_template` longtext COLLATE utf8mb3_bin, PRIMARY KEY (`Id`)
) /*!50100 TABLESPACE `mysql` */ ENGINE=InnoDB DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_bin STATS_PERSISTENT=0 COMMENT='Concurrency control'ERROR 7535 (HY000): Concurrency control refuse to execute query。管理CCL规则
add_ccl_rule:增加规则
dbms_ccl.add_ccl_rule('<Type>','<Schema_name>','<Table_name>',<Concurrency_count>,'<Keywords>');mysql> call dbms_ccl.add_ccl_rule('SELECT', '', '', 10, '');mysql> call dbms_ccl.add_ccl_rule('SELECT', '', '', 20, 'key1');mysql> call dbms_ccl.add_ccl_rule('SELECT', 'test', 't', 20, 'key2');add_ccl_template_rule:增加模板规则
dbms_ccl.add_ccl_rule('<Type>','<Schema_name>','<Table_name>',<Concurrency_count>,'', 'Template_sql');'SELECT c FROM t1 WHERE id=?'的并发数为30。call dbms_ccl.add_ccl_rule('TEMPLATE', 'test', '', 30, '', 'SELECT c FROM t1 WHERE id=4');del_ccl_rule:删除规则
dbms_ccl.del_ccl_rule(<Id>);
mysql> call dbms_ccl.del_ccl_rule(15);
show warnings;查看警告内容。mysql> call dbms_ccl.del_ccl_rule(100);
Query OK, 0 rows affected, 2 warnings (0.00 sec)
mysql> show warnings;+---------+------+----------------------------------------------------+| Level | Code | Message |+---------+------+----------------------------------------------------+| Warning | 7514 | Concurrency control rule 100 is not found in table || Warning | 7514 | Concurrency control rule 100 is not found in cache |+---------+------+----------------------------------------------------+
show_ccl_rule:查看内存中已启用规则
dbms_ccl.show_ccl_rule();
mysql> call dbms_ccl.show_ccl_rule();+------+--------+--------+-------+-------+-------+-------------------+---------+---------+----------+----------+| ID | TYPE | SCHEMA | TABLE | STATE | ORDER | CONCURRENCY_COUNT | MATCHED | RUNNING | WAITTING | KEYWORDS |+------+--------+--------+-------+-------+-------+-------------------+---------+---------+----------+----------+| 17 | SELECT | test | t | Y | N | 30 | 0 | 0 | 0 | || 16 | SELECT | | | Y | N | 20 | 0 | 0 | 0 | key1 || 18 | SELECT | | | Y | N | 10 | 0 | 0 | 0 | |+------+--------+--------+-------+-------+-------+-------------------+---------+---------+----------+----------+
WAITTING的说明如下。flush_ccl_rule:规则生效
dbms_ccl.flush_ccl_rule();
mysql> update mysql.concurrency_control set CONCURRENCY_COUNT = 15 where Id = 18;
Query OK, 1 row affected (0.00 sec)Rows matched: 1 Changed: 1 Warnings: 0mysql> call dbms_ccl.flush_ccl_rule();
Query OK, 0 rows affected (0.00 sec)
功能测试
-- SELECT命令操作表sbtest1并发数为3call dbms_ccl.add_ccl_rule('SELECT', 'test', 'sbtest1', 3, '');-- SELECT命令关键字sbtest2并发数为2call dbms_ccl.add_ccl_rule('SELECT', '', '', 2, 'sbtest2');
-- SELECT命令并发数为2call dbms_ccl.add_ccl_rule('SELECT', '', '', 2, '');mysql> call dbms_ccl.show_ccl_rule();+------+--------+--------+---------+-------+-------+-------------------+---------+---------+----------+----------+| ID | TYPE | SCHEMA | TABLE | STATE | ORDER | CONCURRENCY_COUNT | MATCHED | RUNNING | WAITTING | KEYWORDS |+------+--------+--------+---------+-------+-------+-------------------+---------+---------+----------+----------+| 20 | SELECT | test | sbtest1 | Y | N | 3 | 389 | 3 | 9 | || 21 | SELECT | | | Y | N | 2 | 375 | 2 | 14 | sbtest2 || 22 | SELECT | | | Y | N | 2 | 519 | 2 | 34 | |+------+--------+--------+---------+-------+-------+-------------------+---------+---------+----------+----------+3 rows in set (0.00 sec)