背景
SQL 限流顾名思义,是一种对 SQL 的查询速度进行限制的能力。
一般情况下,我们希望 SQL 查询语句在数据库上的执行速度越快越好。然而当数据库的资源有限,例如在 CPU、IO、内存等某一项资源达到上限时,查询在并发执行时会有激烈的资源争抢,此时有的查询会因为资源不足而出现超时,从而影响用户业务。
为应对突发的数据库请求流量、资源消耗过高的语句访问以及 SQL 访问模型的变化等问题,数据库需要对外提供一个限流方法。
OceanBase 之前支持通过创建 outline 绑定 /*+max_concurrent(N)*/
的方法来对指定 SQL 进行限流(限制这个 SQL 文本的并发数),但不支持关键字限流。
CREATE outline ol_1 ON
SELECT /*+max_concurrent(1)*/ *
FROM t2
WHERE c1 = 1 AND c2 = ?;
有一些用户在使用过程中,会表示 “因为业务方有时候简单粗暴,会出现大量自动重试操作,基于用户的某些标准,希望 OceanBase 在未来具备全局自适应限流能力,自动对每种类型的 SQL 限制并发度,防止重试 SQL 瞬间激增,导致数据库 Load 激增。这样一来,当我们设置全局 SQL 执行的并发度在 10 或 20 的时候,无论历史 SQL 还是新 SQL 都会自动统一,无需运维手动操作,当出现故障时即可快速止损。目前 OCP 具备单独对 SQL 限流的能力,但不能全局限流。”
另一方面,OceanBase 当前创建完 outline 限流规则后,若想限流规则生效,仍需进入 SQL 引擎。使用 outline 的限流逻辑必须要先通过 Parse、Resolve 和 Optimize 阶段生成出执行计划,且在将计划添加进 PlanCache 后才会检查是否触发限流上限。对于一些在 Parse、Resolve 阶段就卡死的 SQL 来说,此类限流方法将失效。OceanBase 需要一种新的限流方式预期能够在 SQL 请求进入 SQL 引擎之前就将其拦住,避免上述场景发生问题。
当前通过 outline 限流逻辑如下:先尝试获取 PlanCache,如果获取到,则直接检查该 SQL 是否超过并发数上限。否则,就会进入完整的 SQL 解析流程,并在向 PlanCache 加入新计划后再进行并发数上限的检查和判断(这个流程看不懂没关系,直接忽略影响也不大)。
因为有用户的业务对 OceanBase 实现全局自适应限流提出了新需求,以及 outline 限流方式存在的一些问题,加之易用性方面的一些考虑,OceanBase 从 435 bp3 版本开始,为大家支持了通过关键字对 SQL 进行限流的功能。
本期课程,就为大家介绍这个 “OceanBase 关键字限流” 的功能~
2. 边学边练,效果拔群
正所谓 “纸上得来终觉浅,实践才能出真知”,强烈推荐大家点击下面的链接,根据在线体验页面左边的实验文档,亲手体验一把 SQL 关键字限流的易用性。
-
在线实验地址:《SQL 关键字限流》。
-
在实验环境中的 “测试限流效果” 部分,设计实验的同学写了一句 “当触发限流规则时,会返回以下错误信息 xxx”,但实验手册中并没有直接给大家构造出这个报错场景。大家可以想想如何快速构造一个被 MAX_CONCURRENCY 限制住的场景?并尝试下在实验环境中,把这个触发限流规则之后的报错给构造出来~
小提示 1:
除了直接把 MAX_CONCURRENCY 设置成 0 以外,在实验环境中,还可以想办法同时跑多条都命中关键字的 SQL,例如:
- 第一条给它用 sleep 关键字 hang 上一段儿时间,然后让它在后台跑。
- 在第一条 SQL 睡觉的这段儿时间内,执行第二条 SQL,预期就可以看到超出并发数限制后的报错了。
obclient -h127.0.0.1 -P2881 -uroot@mysql_tenant -A -Dtest set global ob_query_timeout = 100000000000000; CREATE TABLE product_reviews ( id BIGINT AUTO_INCREMENT PRIMARY KEY, product_id BIGINT, user_id BIGINT, rating INT, comment TEXT, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ); INSERT INTO product_reviews (product_id, user_id, rating, comment) VALUES (1, 1001, 5, 'Excellent smartphone'), (1, 1002, 4, 'Good value for money'), (2, 1003, 5, 'Powerful performance');
drop CONCURRENT_LIMITING_RULE product_reviews_table_limit; CREATE CONCURRENT_LIMITING_RULE IF NOT EXISTS `product_reviews_table_limit` ON test.product_reviews TO 'root'@'%' FOR SELECT WITH MAX_CONCURRENCY = 1; quit obclient -h127.0.0.1 -P2881 -uroot@mysql_tenant -A -Dtest -e "SELECT COUNT(*) FROM product_reviews WHERE product_id > sleep(100);" & obclient -h127.0.0.1 -P2881 -uroot@mysql_tenant -A -Dtest SELECT COUNT(*) FROM product_reviews WHERE product_id = 123;
-
小提示 2:
- 需要先登录 OceanBase 账号,才能初始化屏幕右边的实验环境进行实验。
- 在实验环境里,干什么都可以。大家不要受限于屏幕左边的实验手册,可以天马行空地做一些你感兴趣的事情,或者验证一些你对 OceanBase 官网文档的疑问、以及自己的猜想等等(甚至可以尝试怎么搞能把这个实验环境里的 OBServer 给弄崩)。
- 欢迎大家平时在学习 OceanBase 的过程中,也都能充分利用在线体验页面为您提供的一些实验环境,来体验 OceanBase 中您感兴趣的新特性。
-
课后小测地址:【DBA 实战营】OceanBase SQL 关键字限流。
- 大家完成课后小测,并在小测中上传实验截图,判卷通过后就会自动获取 10 积分,并自动获得抽奖资格,参与抽奖就有机会获得实体礼物或高额积分奖励。