数据库突发高负载、慢SQL抢占资源、业务接口雪崩? 传统限流治标不治本,关键字限流前置拦截,从根源守住数据库稳定性!尤其是OceanBase这类分布式数据库,多租户、高并发场景下,SQL限流更是运维必备技能。今天就深度拆解OceanBase两种限流方案,重点揭秘 关键字限流的实战用法。
SQL限流是一种数据库流量控制机制,用于对特定的SQL请求进行并发或资源使用上的限制,以防止异常或高负载的SQL语句影响整个数据库系统的稳定性与性能。
当某些SQL请求过于频繁或消耗过多资源(如CPU、IO、响应时间等)时,可能会影响其他正常业务的执行。通过设置SQL限流规则,可以:
使用场景
ALTER SYSTEM ENABLE SQL THROTTLE FOR PRIORITY <= 100 USING QUEUE_TIME=0.1;
--对 PRIORITY 小于等于 100 的 Session 上队列等待时间超过 0.1s 的请求限流。
具体限流特征支持情况需要看对应版本的文档说明
参考文档:https://www.oceanbase.com/docs/enterprise-oceanbase-database-cn-10000000000946702
使用 Outline 绑定, 添加
/*+max_concurrent(N)*/这个 Hint。其中,N 表示某类 Query 可同时执行的请求数,实际内部限制的是某个 Plan 可同时执行的请求数;
支持使用文本限流、SQL_ID 限流以及模糊限流三种方式来绑定 Outline。
CREATE [
OR
REPLACE]
OUTLINE outline_name
ON stmt_with_hint [
TO ];
CREATE
OUTLINE outline_name
ON sql_id
USING HINT hint_text;
CREATE [
OR
REPLACE]
FORMAT
OUTLINE outline_name
ON stmt_with_hint [
TO ];
CREATE
FORMAT
OUTLINE outline_name
ON sql_id
USING HINT hint_text;
查看DBA_OB_OUTLINES视图:发现通过ocp为该SQL_ID创建了outline_content为/*+max_concurrent(1) */的outline!
查看该SQL_ID(1FA56D57B98FCA5F4151B385D0C4F736)的执行计划:发现outline已经被用到执行计划里了
+---------+------------+-----------------------------------------------------------------------------------------------------------------------+
| PLAN_ID | OUTLINE_ID | OUTLINE_DATA |
+---------+------------+-----------------------------------------------------------------------------------------------------------------------+
| 234967 | 583343 | /*+BEGIN_OUTLINE_DATA FULL(@"SEL$1" "cjx_test"."t1"@"SEL$1") OPTIMIZER_FEATURES_ENABLE('4.2.1.11') END_OUTLINE_DATA*/ |
| 317638 | 583343 | /*+BEGIN_OUTLINE_DATA FULL(@"SEL$1" "cjx_test"."t1"@"SEL$1") OPTIMIZER_FEATURES_ENABLE('4.2.1.11') END_OUTLINE_DATA*/ |
+---------+------------+-----------------------------------------------------------------------------------------------------------------------+
2 rows in set (0.06 sec)
查看sql_audit:发现后续该sql_id的sql执行都使用了带有outline的执行计划
总结:白屏是通过为sql_id创建 /* max_concurrency(N) */的outline来实现并发限流。
当前创建完outline限流规则后,若想限流规则生效,仍需进入SQL引擎。
使用outline的限流逻辑必须要先通过Parse、Resolve和Optimize阶段生成出执行计划,且在将计划添加进执行计划缓存。后续SQL进入进行快速参数化访问plan_cache后才会检查是否触发限流上限。对于一些在Parse、Resolve阶段就卡死的SQL来说,此类限流方法将失效。需要一种新的限流方式预期能够在SQL请求进入SQL引擎之前就将其拦住。
为此,引入了关键字限流
对于 V4.4.X 版本,该语句从 OceanBase 数据库 V4.4.1 版本开始引入。
CREATE CONCURRENT_LIMITING_RULE [ IF NOT EXISTS ] `ccl_rule_name`
ON `database`.`table`
TO ''@'ip'
FOR { ALL | UPDATE | SELECT | INSERT | DELETE }
filter_options:
[ FILTER BY KEYWORD('KEYWORD1', 'KEYWORD2',…) ]
with_options:
WITH MAX_CONCURRENCY = value1 [per sql]
核心参数解读:
统计粒度:所有命中该规则的 SQL 总并发≤MAX_CONCURRENCY
CREATE CONCURRENT_LIMITING_RULE
IF
NOT
EXISTS product_reviews
-> ON *.*
-> TO '%'@'%'
-> FOR ALL
-> FILTER BY KEYWORD('product_reviews')
->
WITH MAX_CONCURRENCY =
1;
select rating,
sleep(
1)
from product_reviews;
同时执行两个语句
执行结果:命中限流规则
统计粒度:每个格式化后的 SQL 单独计数,各自并发≤1
创建新的限流规则(多了一个PER SQL)
MySQL [test]>
CREATE CONCURRENT_LIMITING_RULE
IF
NOT
EXISTS product_reviews
-> ON *.*
-> TO '%'@'%'
-> FOR
SELECT
-> FILTER BY KEYWORD('product_reviews')
->
WITH MAX_CONCURRENCY =
1 per
sql;
Query OK, 0 rows affected (0.17 sec)
在两个窗口同时分别执行不一样SQL_ID的查询语句
-- 窗口1 SQL
select user_id,rating,
sleep(
1)
from product_reviews
-- 窗口1 SQL_ID: 02E17F50C77BA44C23A4F3B7B031F004
-- 窗口2 SQL
select rating,product_id,
sleep(
1)
from product_reviews
-- 窗口2 SQL_ID: 1FF7D06783EC120A29EE890C85ED15D8
执行结果如下:
执行成功,未命中CCL_RULE
添加一个窗口3,执行和窗口1一样的语句,预期就会命中限流规则报错
从sql_audit也可以查看 CCL_RULE_ID来判断是否命中CCL_RULE
SVR_IP: XX.XX.XX.XX
SVR_PORT: 2882
REQUEST_ID: 1635878
SQL_EXEC_ID: 20545345
TRACE_ID: YB42C0A8054B-000642EF0AE65536-0-0
SID: 297797
CLIENT_IP: XX.XX.XX.XX
CLIENT_PORT: 46744
TENANT_ID: 1004
TENANT_NAME: test
EFFECTIVE_TENANT_ID: 1004
USER_ID: 200001
USER_NAME: root
USER_GROUP: 0
USER_CLIENT_IP: XX.XX.XX.XX
DB_ID: 500001
DB_NAME: test
SQL_ID: 02E17F50C77BA44C23A4F3B7B031F004
QUERY_SQL:
select user_id,rating,
sleep(
1)
from product_reviews
PLAN_ID:
0
AFFECTED_ROWS:
0
RETURN_ROWS:
0
PARTITION_CNT:
1
RET_CODE:
-11087
QC_ID:
0
DFO_ID:
0
SQC_ID:
0
WORKER_ID:
0
EVENT:
P1TEXT:
P1:
0
P2TEXT:
P2:
0
P3TEXT:
P3:
0
LEVEL:
0
WAIT_CLASS_ID:
100
WAIT_CLASS
#: 0
WAIT_CLASS: OTHER
STATE: MAX_WAIT
TIME ZERO
WAIT_TIME_MICRO:
0
TOTAL_WAIT_TIME_MICRO:
0
TOTAL_WAITS:
0
RPC_COUNT:
0
PLAN_TYPE:
0
IS_INNER_SQL:
0
IS_EXECUTOR_RPC:
0
IS_HIT_PLAN:
0
REQUEST_TIME:
1762600230468937
ELAPSED_TIME:
819
NET_TIME:
0
NET_WAIT_TIME:
3
QUEUE_TIME:
240
DECODE_TIME:
1
GET_PLAN_TIME:
440
EXECUTE_TIME:
79
APPLICATION_WAIT_TIME:
0
CONCURRENCY_WAIT_TIME:
0
USER_IO_WAIT_TIME:
0
SCHEDULE_TIME:
0
ROW_CACHE_HIT:
0
BLOOM_FILTER_CACHE_HIT:
0
BLOCK_CACHE_HIT:
0
DISK_READS:
0
RETRY_CNT:
0
TABLE_SCAN:
0
CONSISTENCY_LEVEL:
-1
MEMSTORE_READ_ROW_COUNT:
0
SSSTORE_READ_ROW_COUNT:
0
DATA_BLOCK_READ_CNT:
0
DATA_BLOCK_CACHE_HIT:
0
INDEX_BLOCK_READ_CNT:
0
INDEX_BLOCK_CACHE_HIT:
0
BLOCKSCAN_BLOCK_CNT:
0
BLOCKSCAN_ROW_CNT:
0
PUSHDOWN_STORAGE_FILTER_ROW_CNT:
0
REQUEST_MEMORY_USED:
8565248
EXPECTED_WORKER_COUNT:
0
USED_WORKER_COUNT:
0
SCHED_INFO:
NULL
FUSE_ROW_CACHE_HIT:
0
PS_CLIENT_STMT_ID:
-1
PS_INNER_STMT_ID:
-1
TX_ID:
0
SNAPSHOT_VERSION:
0
REQUEST_TYPE:
2
IS_BATCHED_MULTI_STMT:
0
OB_TRACE_INFO:
NULL
PLAN_HASH:
0
LOCK_FOR_READ_TIME:
0
PARAMS_VALUE:
RULE_NAME:
PARTITION_HIT:
1
TX_INTERNAL_ROUTING:
0
TX_STATE_VERSION:
0
FLT_TRACE_ID:
00064313
-589e-3d45
-641f
-4857b908d45e
PL_TRACE_ID:
NULL
PLSQL_EXEC_TIME:
0
FORMAT_SQL_ID:
2E1AEEDF0CE5A757B4D4BEAF7D16AE89
STMT_TYPE:
SELECT
TOTAL_MEMSTORE_READ_ROW_COUNT:
0
TOTAL_SSSTORE_READ_ROW_COUNT:
0
PROXY_USER:
SEQ_NUM:
0
NETWORK_WAIT_TIME:
0
PLSQL_COMPILE_TIME:
0
INSERT_DUPLICATE_ROW_COUNT:
0
CCL_RULE_ID:
500016
CCL_MATCH_TIME:
148
oceanbase.DBA_OB_CCL_RULES GV$OB_SQL_CCL_STATUS
0 ALL
1 SELECT
2 UPDATE
3 INSERT
4 DELETE
SQL限流是数据库运维的最后一道防线,OceanBase关键字限流彻底解决了传统限流的滞后性问题,实现 前置拦截、精准控流、低耗高效。
你在运维实战中,曾遭遇哪些棘手难题?欢迎在评论区交流!
为感谢瑞蓝创粉丝支持,我们特意设置宠粉福利
https://mp.weixin.qq.com/s/Tl1MBGKjjBVzTmVq2IY1gA
🎯 获奖规则: 在【瑞蓝创软件】公众号本条推文(上方链接)评论区留言参与互动
留言点赞量 前 3 名小伙伴,可以免费获取“OBCA V4 考券”1张!
更多福利活动正在路上,超多运维干货持续更新!微信公众号【瑞蓝创软件】
关注不迷路
,
福利不错过
!

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70047467/viewspace-3114641/ ,如需转载,请注明出处,否则将追究法律责任。