OceanBase 中 Zone、OBServer 与分区表之间的关系
一、先看整体关系
OceanBase 可以从以下层次理解:
text
OceanBase 集群(Cluster)
│
├── Zone 1 逻辑故障域 / 可用区
│ ├── OBServer 1 承载租户资源单元
│ └── OBServer 2
│
├── Zone 2
│ ├── OBServer 3
│ └── OBServer 4
│
└── Zone 3
├── OBServer 5
└── OBServer 6
租户(Tenant)
└── 资源池(Resource Pool)
└── 资源单元(Unit) ── 分布在各个 OBServer 上
└── 分区副本(Partition Replica)
可以先记住下面这句话:
Zone 是故障域,OBServer 是承载数据库服务和资源的节点,分区是表数据的分布单位,副本是分区的冗余拷贝。
它们解决的问题不同:
| 概念 | 主要含义 | 解决的问题 |
|---|---|---|
| Cluster | 一组协同工作的 OceanBase 服务节点 | 组成一个分布式数据库集群 |
| Zone | 集群中的逻辑故障域,通常对应一个机房、可用区或容灾域 | 故障隔离和副本跨域部署 |
| OBServer | 运行 OceanBase 数据库服务的节点或进程 | 实际承载计算、内存、磁盘和分区副本 |
| Tenant | 集群内的数据库租户 | 资源和数据访问的隔离边界 |
| Unit | 租户在某个 OBServer 上获得的一份资源单元 | 为租户提供 CPU、内存、磁盘等资源 |
| Partition | 表按照分区规则拆分出来的数据范围或数据集合 | 数据分布、并行处理和分区裁剪 |
| Replica | 某个分区在不同位置保存的一份副本 | 高可用、容灾和故障切换 |
二、Zone 是什么
2.1 Zone 是逻辑上的故障域
Zone 可以理解为集群中的一个逻辑部署区域,常见映射包括:
- 一个物理机房。
- 一个云可用区(Availability Zone)。
- 一个具有独立网络、电力或容灾属性的部署区域。
Zone 本身不是一张表,也不负责定义表的分区规则。它主要用于描述节点的故障域和副本的放置位置。
例如,三个 Zone 可以表示三个可用区:
text
OceanBase 集群
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
Zone A Zone B Zone C
可用区 A 可用区 B 可用区 C
如果一个分区的三个副本分别放在 Zone A、Zone B、Zone C,那么即使其中一个 Zone 整体发生故障,其他 Zone 仍可能保留可用副本。
2.2 Zone 不等于一台机器
一个 Zone 通常可以包含多个 OBServer:
text
Zone A
├── OBServer A1
├── OBServer A2
└── OBServer A3
因此下面两种说法含义不同:
- "分区副本位于 Zone A":表示它位于 Zone A 这个故障域内,但还没有说明具体节点。
- "分区副本位于 OBServer A1":表示已经定位到了具体承载节点。
生产环境中,Zone 和 OBServer 的数量、命名及物理映射应以实际部署为准。不要仅凭 Zone 数量推断 OBServer 数量,也不要把 Zone 数量简单当作分区数量。
三、OBServer 是什么
OBServer 是 OceanBase 的数据库服务节点,通常运行在物理机或虚拟机上。它负责承载实际的数据库工作,包括:
- 接收和执行 SQL 请求。
- 保存本节点上的分区副本数据。
- 使用本节点的 CPU、内存和磁盘资源。
- 参与事务处理、日志复制和副本选举。
- 在集群调度下承担分区迁移、负载均衡和副本恢复。
可以把 OBServer 看作"真正运行数据库服务并承载数据的节点",而不是把它理解成某一个表或某一个分区。
一个 OBServer 可以同时承载多个租户的资源单元,也可以承载同一个租户的多个分区副本:
text
OBServer A1
├── 租户 T1 的 Unit
│ ├── orders 分区 p202609 的副本
│ └── orders 分区 p202610 的副本
│
└── 租户 T2 的 Unit
└── customers 分区 p0 的副本
这里的 Unit 是资源和调度层面的概念。应用一般不需要直接操作 Unit,而是通过租户和逻辑表访问数据。
四、分区表是什么
分区表仍然是一张逻辑表。应用访问的是表名,例如 orders,而不是分别访问 p202609、p202610 这些分区名。
text
逻辑表:orders
│
├── 分区 p202609:2026 年 9 月订单
├── 分区 p202610:2026 年 10 月订单
└── 分区 p202611:2026 年 11 月订单
分区规则决定一行数据属于哪个分区,例如:
HASH (id):根据分区键的哈希结果选择分区。RANGE COLUMNS (created_at):根据时间范围选择分区。LIST:根据枚举值或类别选择分区。
以按月 RANGE 分区为例:
sql
CREATE TABLE orders (
id BIGINT NOT NULL,
user_id BIGINT NOT NULL,
amount DECIMAL(18, 2) NOT NULL,
created_at DATETIME NOT NULL,
PRIMARY KEY (created_at, id)
)
PARTITION BY RANGE COLUMNS (created_at) (
PARTITION p202609 VALUES LESS THAN ('2026-10-01'),
PARTITION p202610 VALUES LESS THAN ('2026-11-01'),
PARTITION p_future VALUES LESS THAN (MAXVALUE)
);
在这个例子中:
2026-09-15的订单进入p202609。2026-10-20的订单进入p202610。- 2026 年 11 月及之后的数据进入
p_future,直到后续维护分区边界。
分区解决的是"表内数据如何拆分和路由"的问题;它本身不等于副本,也不直接指定某个物理节点。
五、分区与副本的关系
一个分区通常会有多份副本。每一份副本都表示同一个分区的数据内容,而不是新的业务分区。
text
逻辑表 orders
│
└── 分区 p202609
├── 副本 1:Zone A / OBServer A1 ← 可能是主副本
├── 副本 2:Zone B / OBServer B1
└── 副本 3:Zone C / OBServer C1
这里要区分:
text
分区:把表的数据拆成不同部分
副本:把同一个分区的数据保存多份
因此,如果 orders 有 3 个分区,每个分区有 3 个副本,底层可能有 9 个分区副本,但应用仍然只看到一张 orders 表。
5.1 主副本和从副本
对于某个分区的多个副本,通常会有一个提供主服务的副本,其他副本用于复制和故障接管。实际角色名称、读写策略和可用性行为应以 OceanBase 版本及副本类型配置为准。
可以用简化模型理解:
text
客户端 SQL
│
▼
路由 / SQL 执行层
│
├── 找到目标分区 p202609
│
└── 访问该分区的合适副本
├── 主副本:处理写入和相关事务
└── 其他副本:同步数据,故障时参与接管
副本之间的数据一致性、日志同步、选举和故障切换由 OceanBase 的分布式机制负责,应用不需要手工向每个副本写入一遍。
5.2 为什么副本通常跨 Zone 放置
如果同一个分区的所有副本都放在一个 Zone,那么该 Zone 整体故障时,副本可能同时不可用。跨 Zone 放置可以降低单个机房或可用区故障造成的数据不可用风险:
text
orders.p202609
│
┌──────────────┼──────────────┐
▼ ▼ ▼
Zone A Zone B Zone C
副本 1 副本 2 副本 3
OBServer A1 OBServer B1 OBServer C1
这只是逻辑示意图。具体副本数、副本类型、Zone 放置策略和是否允许同 Zone 多副本,需要结合租户配置、集群规格及 OceanBase 版本确认。
六、从一行数据到 OBServer 的完整路径
以按 created_at 按月分区的 orders 表为例,一行订单数据的大致定位过程如下:
text
INSERT INTO orders (..., created_at)
VALUES (..., '2026-09-15 10:30:00');
│
▼
根据分区规则计算目标分区
│
▼
orders.p202609
│
▼
找到该分区的副本位置
┌───────┼───────┐
▼ ▼ ▼
Zone A Zone B Zone C
副本 1 副本 2 副本 3
│
▼
由对应 OBServer 承载和处理
应用只需要执行:
sql
INSERT INTO orders (id, user_id, amount, created_at)
VALUES (1000001, 1001, 99.90, '2026-09-15 10:30:00');
应用不需要指定:
- 写入哪个分区。
- 写入哪个 Zone。
- 写入哪个 OBServer。
- 向哪个副本发送第二份或第三份数据。
这些工作由数据库根据分区规则、分区副本位置、租户资源和集群调度状态完成。
七、查询时分区裁剪与节点访问
对于按时间分区的表,查询条件包含分区键时,数据库可以进行分区裁剪:
sql
SELECT *
FROM orders
WHERE created_at >= '2026-09-01'
AND created_at < '2026-10-01';
逻辑上可以理解为:
text
查询 orders
│
▼
根据 created_at 判断只需要 p202609
│
▼
访问 p202609 的合适副本
│
├── Zone A / OBServer A1
├── Zone B / OBServer B1
└── Zone C / OBServer C1
分区裁剪减少的是需要检查的分区数量,不代表查询一定只经过一个 OBServer,也不代表一定只读取一个副本。实际访问路径还可能受到以下因素影响:
- 主副本位置和当前副本角色。
- SQL 是否需要跨分区查询。
- 是否使用局部索引或全局索引。
- 是否发生分布式事务或跨分区聚合。
- SQL 路由、并行执行和负载均衡策略。
如果查询没有带分区键,例如:
sql
SELECT *
FROM orders
WHERE user_id = 1001;
数据库可能需要访问多个分区,再由执行计划和索引决定具体扫描范围。因此,分区键应尽量与主要查询、归档和数据生命周期操作相匹配。
八、一个完整的拓扑示例
假设:
- 集群有 3 个 Zone:
zone_a、zone_b、zone_c。 - 每个 Zone 有 2 台 OBServer。
orders按月份划分为 3 个分区。- 每个分区有 3 个副本,分别放在 3 个 Zone。
示意拓扑如下:
text
OceanBase Cluster
│
├── zone_a
│ ├── observer_a1
│ │ ├── orders.p202609 副本
│ │ └── orders.p202610 副本
│ └── observer_a2
│ └── orders.p202611 副本
│
├── zone_b
│ ├── observer_b1
│ │ ├── orders.p202609 副本
│ │ └── orders.p202611 副本
│ └── observer_b2
│ └── orders.p202610 副本
│
└── zone_c
├── observer_c1
│ ├── orders.p202610 副本
│ └── orders.p202611 副本
└── observer_c2
└── orders.p202609 副本
从这个例子可以看出:
- 一个 Zone 可以有多个 OBServer。
- 一个 OBServer 可以承载多个分区副本。
- 一个分区可以在多个 Zone 和多个 OBServer 上拥有副本。
- 分区数量和副本数量是两个维度,不能混为一谈。
- 应用仍然只访问逻辑表
orders,不需要感知上述物理布局。
九、分区、Zone、OBServer 的职责边界
| 问题 | 由什么决定 | 说明 |
|---|---|---|
| 一行数据属于哪个分区 | 分区键和分区规则 | 例如按 created_at 的月份进入对应 RANGE 分区 |
| 分区副本有几份 | 副本策略、租户和集群配置 | 不是由 PARTITION BY 单独决定 |
| 副本放在哪些 Zone | 副本放置策略和 Zone 布局 | 用于故障隔离和容灾 |
| 副本具体落在哪个 OBServer | 资源单元布局和集群调度 | 可能随迁移、扩缩容和负载均衡变化 |
| SQL 访问哪个副本 | 路由、主副本角色、读写策略 | 应用一般不直接指定物理节点 |
| 哪些分区需要被扫描 | 查询条件和执行计划 | 使用分区键过滤时更容易发生分区裁剪 |
可以用一句话总结:
分区规则决定数据属于哪一部分;副本策略决定这部分数据保存几份;Zone 决定故障域;OBServer 承载这些副本并执行数据库工作。
十、常见误区
误区一:一个 Zone 就是一台 OBServer
不准确。一个 Zone 可以包含多个 OBServer;Zone 是故障域或部署区域,OBServer 是实际承载服务的节点。
误区二:分区就是一台物理服务器上的一张表
不准确。分区是逻辑表的一部分,分区副本可能由不同 Zone 中的多个 OBServer 承载。
误区三:创建 8 个分区就会自动对应 8 个 Zone
不准确。PARTITIONS 8 只表示创建 8 个逻辑分区,不表示创建 8 个 Zone,也不表示每个分区固定对应一台服务器。
误区四:副本就是另一个分区
不准确。副本是同一个分区的数据冗余副本。orders.p202609 的多个副本仍然属于同一个逻辑分区。
误区五:分区裁剪等于只访问一台 OBServer
不准确。分区裁剪表示减少需要检查的分区范围;实际执行可能涉及副本选择、并行执行、跨节点计算或多个 OBServer。
误区六:应用可以通过分区名指定数据放置节点
通常不应这样理解。应用访问逻辑表即可。分区到 Zone、OBServer 的具体布局属于数据库部署、租户资源和调度管理范畴。
十一、如何查看相关信息
11.1 查看分区定义
sql
SHOW CREATE TABLE orders;
也可以查看分区元数据:
sql
SELECT
TABLE_NAME,
PARTITION_NAME,
PARTITION_METHOD,
PARTITION_EXPRESSION,
PARTITION_DESCRIPTION
FROM information_schema.PARTITIONS
WHERE TABLE_SCHEMA = DATABASE()
AND TABLE_NAME = 'orders'
ORDER BY PARTITION_ORDINAL_POSITION;
11.2 查看 Zone 和 OBServer
不同 OceanBase 版本、部署方式和权限下,可使用的视图或命令可能存在差异。常见排查方向包括:
sql
SHOW PARAMETERS LIKE 'zone%';
以及查询集群、Zone、服务器和租户相关的系统视图。正式环境中应以目标版本的官方文档和实际权限为准,不要直接假设某个系统视图在所有版本都存在。
排查时通常需要确认:
- 集群包含哪些 Zone。
- 每个 Zone 中有哪些 OBServer。
- 租户资源单元位于哪些 OBServer。
- 目标表的各分区副本位于哪些节点。
- 某个分区当前由哪个副本提供主服务。
十二、最终记忆方式
text
表(orders)
└── 分区(p202609)
└── 副本(多个)
└── 位于不同 Zone
└── 由 Zone 内的 OBServer 承载
或者记成:
text
分区:拆开存
副本:复制存
Zone:按故障域放
OBServer:真正承载和执行
分区表设计关注的是数据如何拆分、如何查询和如何维护;Zone 与 OBServer 设计关注的是资源承载、故障隔离、高可用和数据副本如何分布。二者通过"分区副本放置"连接起来,但不是同一个层次的概念。