---
title: CPU 与内存超卖问题简介-OceanBase数据库使用指南
description: 了解OceanBase数据库在实际应用中关于 CPU 与内存超卖问题简介相关的常见问题和使用技巧，帮助您快速解决 CPU 与内存超卖问题简介的难题。
---
切换语言

- 中文站 - 简体中文
- International - English
- 日本站 - 日本語

划线反馈

# CPU 与内存超卖问题简介

更新时间：2026-05-12 08:31

适用版本： V2.1.x、V2.2.x、V3.1.x、V3.2.x 内容类型：TechNote  

本文详述 OceanBase 数据库中 CPU 和内存超卖的风险与收益。

## 适用版本

OceanBase 数据库 V4.0 之前的版本。

## CPU 和内存的超卖

- 如果一个 OBServer 上放置的所有 Unit 的 MAX_CPU 的值加起来超过这个 OBServer 的可用 CPU 总数，则表示该 OBServer 上的 CPU 是超卖的。
 - 同理，如果所有 Unit 的 MAX_MEMORY 加起来超过该 OBServer 上可以分配的 Memory，则表示该 OBServer 上的 Memory 是超卖的。
 - OBServer 资源超卖的比例受配置项 `resource_hard_limit` 的控制，假设 `resource_hard_limit=200`，那就意味着可以超卖成 2 倍，即 16 个 CPU 可以超卖成 32 个，16G 的内存可以超卖成 32G。
 - 超卖是通过牺牲稳定性来获取更高的资源利用率的方案，是否要开启超卖需要根据应用特性和应用的 SLA 要求仔细评估。例如，一个比较适合的场景就是业务的研发测试环境。

#### 注意

即使在分配资源的时候没有超卖，在实现 CPU 资源隔离时，Unit 可以使用的 CPU 并没有严格限制在 MAX_CPU 的值, 这个意义上的 CPU 默认是超卖的。更多 CPU 超卖的介绍信息可参见本文中的 CPU 隔离 。

## 内存隔离

- 内存是个刚性的资源，也就是内存一旦被占用了，很难保证能快速收回。所以内存是不适合超卖的。
 - Unit 的内存上限由 MAX_MEMORY 决定，Unit 的 MIN_MEMORY 仅用来决定 Block Cache 的挤占时机，除此之外没有其它用途。
 - 生产系统中推荐将 MIN_MEMORY 和 MAX_MEMORY 设置为相等的值。

## CPU 隔离

相比于内存，CPU 是更弹性的资源，所以 OBServer 目前允许一个 Unit 使用的物理 CPU 超过分配给它的配额。

在 OceanBase 数据库 V3.2.3 及之前版本，主要通过控制线程数来控制 CPU 的占用。

### 线程分类

- OBServer 会启动很多不同功能的线程，细化的分类请参考 observer 线程的相关章节，本节按照最粗略的标准可以分为以下两类：
     - 一类是处理 SQL 和事务提交的线程，统称为 Worker 线程。
     - 其余的是处理网络 IO、磁盘 IO、Compaction 以及定时任务的线程。
 - Worker 线程是分租户的，非 Worker 线程是所有租户共享的。本节的租户 CPU 隔离都是针对 Worker 线程的。

### 基于线程数的 CPU 隔离

- Unit 的 CPU 隔离是通过一个 Unit 的活跃 Worker 线程数实现的。
 - 由于 SQL 执行过程中可能会有 IO 等待、锁等待等，所以一个线程无法用满一个物理 CPU。故在缺省配置下，OBServer 会给每个 CPU 启动 4 个线程，4 这个倍数可以通过配置 `cpu_quota_concurrency` 来控制。这就意味着如果一个 Unit 的 MAX_CPU 是10，那么它能同时运行的活跃线程是 40。

### 基于 Cgroup 的 CPU 隔离

- 开启 Cgroup 后最大的变化是不同租户的 Worker 线程放到不同的 Cgroup 目录内，租户间的 CPU 隔离效果会更好。
 - 最后的隔离效果如下：
     - 如果一个 OBServer 上只有一个租户负载很高，其余租户比较空闲，那么这个负载高的租户的 CPU 也会受到 MAX_CPU 的限制。
     - 延续上面的场景，如果有多个空闲的租户的负载上升了，导致物理 CPU 不够了，Cgroup 会按照权重分配时间片。

### 大查询处理

我们认为相比于大查询，让短查询尽快返回对用户更有意义，即大查询的查询优先级更低，当大查询和短查询同时争抢 CPU 时，系统会限制大查询的 CPU 使用。

当一个线程执行的 SQL 查询耗时太长，这条查询就会被判定为大查询, 一旦判定为大查询，执行大查询的 Worker 会等在一个 Pthread Condition 上，这样就为其它的 Worker 线程让出了 CPU。

具体实现上，OBServer 在代码中插入了很多检查点，Worker 线程在运行过程中会通过检查点定期检查自己的状态，如果判断应该挂起，那么线程就会等待在一个 Pthread Condition 上，等到合适的时机再被唤醒。

如果同时有大查询和小查询，大查询最多占用 30% 的 Worker 线程，30% 这个百分比值可以通过配置项 `large_query_worker_percentage` 来设置。

有两点需要说明：

- 当没有小查询的时候，大查询可以用到全部的 Worker 线程。只有当同时有大查询和小查询时，30% 的比例才生效。
 - 一个 Worker 因为执行大查询被挂起时，作为补偿，系统可能会新创建一个 Worker 线程。但是总的 Worker 线程不能超过 MAX_CPU 的 10 倍，10 这个倍数可以通过配置项 `workers_per_cpu_quota` 来设置。

**提前识别大查询**

由于 OBServer 挂起一个大查询线程，就会启动一个新的 Worker 线程。但是如果有大量大查询涌入，OBServer 新创建的线程还是被用来处理大查询，很快达到 Worker 数上限，在这批大查询消耗完之前就没有机会再处理短查询了。为了优化这个场景，OBServer 会在 SQL 开始执行之前预判它是不是大查询，预判的本质就是估计 SQL 的执行时间。预判主要依据以下假设场景：如果两条 SQL 的执行 Plan 是一样的，可以猜测它们的执行时间也是相似的，这样就可以用 Plan 最近的执行时间来判断 SQL 会不会是大查询。如果某条 SQL 被预判为大查询，那么该查询就会被放入一个特殊的大查询队列，其 Worker 线程会被释放，系统就会接着执行后面的请求了。

上一篇

[如何精准查看租户 IOPS 的使用量](https://www.oceanbase.com/knowledge-base/oceanbase-database-1000000004521621)

下一篇

[如何配置 OBServer 内存使用量](https://www.oceanbase.com/knowledge-base/oceanbase-database-20000000031) ![有帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*y6ocSqN8cqsAAAAAAAAAAAAAARQnAQ)![无帮助](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*BG9IQJyLHF8AAAAAAAAAAAAAARQnAQ)![反馈](https://gw.alipayobjects.com/mdn/ob_asset/afts/img/A*eTWdQKCRKHwAAAAAAAAAAAAAARQnAQ)[AI](https://www.oceanbase.com/obi) 咨询热线
