OceanBase 中的非机动车道 —— SQL 限流技巧分享
首先为大家推荐这个 OceanBase 开源负责人老纪的公众号 “老纪的技术唠嗑局”,会持续更新和 OceanBase 相关的各种技术内容。欢迎感兴趣的朋友们关注!
定场诗《回家的路》
从公司回家时,
每次都会路过丽水路。
这条路上植被很多,
旁边就是京杭大运河。
可惜路又长又窄,
长四公里,窄到机动车道和非机动车道被合二为一。
回家路上经常看到这样的景象,
几辆自行车骑上了这条说不清是机动车道还是非机动车道的路,
后面的汽车怕撞到自行车,
只能一路陪着骑车的人慢悠悠地开。
背景
大家先思考这样一个问题:在一条机动车道和非机动车道被合二为一的道路上,单位时间内,大家会选择让十辆汽车通过,还是选择让一辆自行车和一辆汽车通过?我个人觉得,让它更快速地通过大量汽车,才能让这条路发挥出更大的作用。

在 AP、TP 业务混布的场景下,因为 CPU 资源有限,OceanBase 认为,让 CPU 尽量先服务更大量的 TP 小请求更有意义。
大查询的判定时机
如果要抓出大查询,就需要判定一条 SQL 是否属于大查询。
OceanBase 中有一个集群级的配置项叫做 large_query_threshold,默认值是 5 秒。
第一次执行 Query 时,因为无法提前预估 Query 的执行时间,所以默认不是大查询(这里其实还是有一些改进空间的)。
如果不是第一次执行这条 Query,因为 Plan Cache 中已经缓存了这条 Query 的计划,所以会根据 Plan Cache 中缓存的之前这条 Query 的平均执行时间,来判定是否属于大查询。

大查询的限制策略
如果 Query 被判定为大查询,则会被直接丢到大查询队列重试,让出当前工作线程。

大查询有单独的线程组调度执行,该线程组与普通工作线程组对等。相当于数据库系统自动会为大查询开辟了一条 “非机动车道”。

大查询队列中的 Query,会受配置项 large_query_worker_percentage(默认值 30%)控制。效果类似于为大查询被单独开了一个资源组,这个资源组内被限制只能使用 30% 的 CPU 资源进行计算。
限流技巧分享
如果突然出现多个第一次执行的大查询,普通工作线程都被占用了怎么办?
缓解方式是:kill 数据库的 session,重连即可恢复。
因为 kill session 之后,Plan Cache 依然会缓存没执行完的 Query 的计划和记录曾经的执行时间。重连 session 之后,大查询就会在编译期通过大查询预判,进入大查询队列,不再占用普通工作线程。
PX 线程怎么限制资源占用?
PX 线程(并行执行工作线程)有独立的线程组,不会受到大查询的限制。大查询队列只会影响普通工作线程组。
这里有一点需要说明:当没有小查询的时候,大查询可以占用全部普通工作线程组的资源。只有当同时有大查询和小查询时,默认 30% 的比例才生效。

因为并行执行本就不应该通过大查询队列来进行限制:一边要用更多资源让 Query 并行执行,跑的更快,一边又要限制不能用更多资源。PX 线程如果要进行资源限制和隔离,还是需要用到上周提到的资源组(resource group)。
SQL 限流功能
最后顺带介绍 OceanBase 中几个和 SQL 限流相关的功能。
使用文本限流
如果要限制某类 SQL 请求执行流量,可以通过创建 outline,添加 /*+max_concurrent(N)*/ 这个 hint,N 表示某类 Query 同时可执行的请求数(实际内部限制的是某类 Plan 同时执行的请求个数)。
语法:
CREATE [OR REPLACE]
OUTLINE outline_name
ON stmt [TO target_stmt];
举例:
create table t1(c1 int, c2 int);
-- ? 表示通配符,限制这类请求个数最多为 0
create outline ol_1 on
select /*+max_concurrent(0)*/ *
from t1
where c1 = 1 and c2 = ?;
-- 执行失败
select *
from t1
where c1 = 1 and c2 = 0;
ERROR 5268 (HY000): SQL reach max concurrent num 0
-- 执行失败
select *
from t1
where c1 = 1 and c2 = 1;
ERROR 5268 (HY000): SQL reach max concurrent num 0
-- 执行成功
select *
from t1
where c1 = 12345 and c2 = 2;
Empty set (0.01 sec)
模糊限流
语法:
CREATE [OR REPLACE]
FORMAT OUTLINE outline_name
ON format_stmt [TO format_target_stmt]
其中 format_stmt 表示归一化后的 SQL,归一化规则如下:
- 归一化常量参数
- 归一化为大写
- 忽略空格、换行符等非语法定义符号差异
- 对于in表达式,将会做归一化
obclient>
select
statement_digest_text(
'select * from
t1 where c1 in (1, 2) and c2 = 3'
);
result : SELECT * FROM T1 WHERE C1 IN (...) AND C2 = ?
1 row in set (0.00 sec)
举例:
-- 创建 format outline
create format outline fmt_otl
on
select /*+max_concurrent(0)*/ *
from t1
where c1 in (?, ?) and c2 = ?;
-- 执行失败
select *
from t1
where c1 in (1)
and c2 = 2;
ERROR 5268 (HY000): SQL reach max concurrent num 0
-- 执行失败
select *
from t1
where c1 in (1, 2)
and c2 = 3;
ERROR 5268 (HY000): SQL reach max concurrent num 0
-- 执行失败
select *
from t1
where c1 in (1, 2, 3)
and c2 = 4;
ERROR 5268 (HY000): SQL reach max concurrent num 0
老纪的技术唠嗑局 不仅希望能持续给大家带来有价值的技术分享,也希望能和大家一起为开源社区贡献力量。如果你对 OceanBase 开源社区认可,点亮一颗小星星 吧!你的每一个Star,都是我们努力的动力~
https://github.com/oceanbase/oceanbase
OceanBase 中的非机动车道 —— SQL 限流技巧分享的更多相关文章
- 【Distributed】限流技巧
一.概述 1.1 高并发服务限流特技 1.2 为什么要互联网项目要限流 1.3 高并发限流解决方案 二.限流算法 2.1 计数器 2.2 滑动窗口计数 2.3 令牌桶算法 使用RateLimiter实 ...
- ASP.NET Core中使用固定窗口限流
算法原理 固定窗口算法又称计数器算法,是一种简单的限流算法.在单位时间内设定一个阈值和一个计数值,每收到一个请求则计数值加一,如果计数值超过阈值则触发限流,如果达不到则请求正常处理,进入下一个单位时间 ...
- ASP.NET Core中使用滑动窗口限流
滑动窗口算法用于应对请求在时间周期中分布不均匀的情况,能够更精确的应对流量变化,比较著名的应用场景就是TCP协议的流量控制,不过今天要说的是服务限流场景中的应用. 算法原理 这里假设业务需要每秒钟限流 ...
- ASP.NET Core中使用令牌桶限流
在限流时一般会限制每秒或每分钟的请求数,简单点一般会采用计数器算法,这种算法实现相对简单,也很高效,但是无法应对瞬时的突发流量. 比如限流每秒100次请求,绝大多数的时间里都不会超过这个数,但是偶尔某 ...
- 令牌桶限流思路分享(PHP+Redis实现机制)
一 .场景描述 在开发接口服务器的过程中,为了防止客户端对于接口的滥用,保护服务器的资源, 通常来说我们会对于服务器上的各种接口进行调用次数的限制.比如对于某个 用户,他在一个时间段(interval ...
- javascript中关于&& 和 || 表达式的小技巧分享
如果你还是新手, 而且读完所有这些技巧的详解和每种技巧是如果工作的以后运用它们, 你会写出更加简练高效的JavaScript程序. 确实, JavaScript高手已经运用这些技巧写出了很多强大, 高 ...
- Redis解读(4):Redis中HyperLongLog、布隆过滤器、限流、Geo、及Scan等进阶应用
Redis中的HyperLogLog 一般我们评估一个网站的访问量,有几个主要的参数: pv,Page View,网页的浏览量 uv,User View,访问的用户 一般来说,pv 或者 uv 的统计 ...
- ASP.NET Core中使用漏桶算法限流
漏桶算法是限流的四大主流算法之一,其应用场景各种资料中介绍的不多,一般都是说应用在网络流量控制中.这里举两个例子: 1.目前家庭上网都会限制一个固定的带宽,比如100M.200M等,一栋楼有很多的用户 ...
- 限流&熔断的考量
限流的原则,是尽量在流量源头限,并且是需要依据现有团队所掌握的技能来. 如上最左侧便是主要流量的来源入口,首先就要限制的地方就是slb节点的income流量 slb节点的流量特点是啥?加限流怎么加?限 ...
- 基于令牌桶算法实现的SpringBoot分布式无锁限流插件
本文档不会是最新的,最新的请看Github! 1.简介 基于令牌桶算法和漏桶算法实现的纳秒级分布式无锁限流插件,完美嵌入SpringBoot.SpringCloud应用,支持接口限流.方法限流.系统限 ...
随机推荐
- Flask应用实战经验总结:使用工厂函数创建app与uWSGI服务部署启动失败解决方案
在 Flask 应用开发中,使用工厂函数创建应用实例,并借助 uWSGI 服务进行部署,是常见且高效的组合. 然而,在实际操作过程中,uWSGI 配置文件与应用启动函数之间的关系复杂,容易引发各种问题 ...
- 深入理解CPU的调度原理
前言 软件工程师们总习惯把OS(Operating System,操作系统)当成是一个非常值得信赖的管家,我们只管把程序托管到OS上运行,却很少深入了解操作系统的运行原理.确实,OS作为一个通用的软件 ...
- Oracle for 循环
Oracle for in loop 循环的一些实例,以作学习和加强使用熟练度及场景应用. 一些技巧 for 语句后面的 loop end loop 可以类比成 c#/java 等编程语言 for 语 ...
- 从客户端(XXX)中检测到有潜在危险的 Request.Form 值
维护别人的某功能模块的时候,页面返回如下错误信息: [HttpRequestValidationException (0x80004005): 从客户端(TextBox1="<?xml ...
- study PostgreSQL【3-get数据库中all表以及表的字段信息】
get一表的字段相关信息: SELECT col_description(a.attrelid,a.attnum) as comment,pg_type.typname as typename,a.a ...
- kettle介绍-Step之If field value is null
If field value is null介绍 替换NULL值步骤可以将输入流中所有字段的空值进行替换,也可以指定一种类型下的空值进行替换,还可以指定一个字段下的空值进行替换 三种替换NULL模式 ...
- FastAPI数据库连接池配置与监控
title: FastAPI数据库连接池配置与监控 date: 2025/04/28 00:13:02 updated: 2025/04/28 00:13:02 author: cmdragon ex ...
- 119K star!无需GPU轻松本地部署多款大模型,DeepSeek支持!这个开源神器绝了
嗨,大家好,我是小华同学,关注我们获得"最新.最全.最优质"开源项目和高效工作学习方法 "只需一行命令就能在本地运行Llama 3.DeepSeek-R1等前沿大模型,支 ...
- Jeesite5:Star24k,Spring Boot 3.3+Vue3实战开源项目,架构深度拆解!让企业级项目开发效率提升300%的秘密武器
企业级应用开发的需求日益增长.今天,我们要介绍的是一个在GitHub上广受好评的开源项目--Jeesite5.这不仅是一个技术框架,更是企业级应用开发的加速器.接下来,我们将深入探讨Jeesite5的 ...
- DeepSeek+Coze实战:如何从0到1打造一个热点监控智能体
大家好,我是汤师爷,专注AI智能体分享~ 短视频小白经常会遇到这样的困扰. 每天花大量时间刷视频,想要找到你所在赛道的爆款内容,却总是难以系统地整理和分析? 想要批量获取某个关键词的爆款视频数据,但是 ...