上篇把 OB 在 Docker 里跑起来、连上 sys 租户看了一眼,算是”能开机了”。但 sys 是系统租户,不是给你放业务数据的——真正要用起来,得先搞懂 OB 的多租户和资源模型,这也是它和我以前用的单机库差别最大的地方。这篇就接着讲:怎么建一个业务租户、客户端怎么连、以及数据到底是怎么”散”到各节点去的。

仍然是学习笔记,不是官方手册。里面建租户的命令我标了”以你本地环境为准”,因为 MINI_MODE 单机环境的 zone 名、可用资源跟我这边不一定一样,照抄前先 SHOW ZONES; 看一眼。


1. 先搞懂三层模型:租户 / 资源池 / Unit

我一开始以为”连上数据库就能建库开干”,结果被现实教了——OB 里资源是分层管的:

  • Unit(资源单元):描述”在某台 OBServer 上分给某个租户多少资源”的容器,含 CPU、内存、日志盘大小。可以类比成一个轻量虚拟机。
  • Resource Pool(资源池):由一个或多个同规格的 Unit 组成,绑定到指定的 Zone 上,然后整体分配给某个租户。
  • Tenant(租户):最终给业务用的独立数据库实例,能选 MySQL 或 Oracle 兼容模式,它手里的资源就来自拥有的 Resource Pool。

所以整条关系是:Cluster → Tenant → Database → Table,而 Unit / Pool 是”资源怎么切、分给谁”的载体。建业务租户的正确顺序是 先 Unit,再 Pool,最后 Tenant,跳过前两步直接 CREATE TENANT 会报错——这是我踩的第一个坑。

把这几层关系画出来,配合后面 OBProxy 的路由,会清楚很多:

多租户与 OBProxy 路由

集群里多个租户彼此隔离;应用只连 OBProxy,由它把 SQL 路由到对应主副本。


2. 动手:建一个 MySQL 租户

下面以本地单机(MINI_MODE)为例。开头先确认你环境里的 zone 名和资源占用,别照抄我的 zone1:

SHOW ZONES;
-- 或者看更细的信息
SELECT * FROM oceanbase.DBA_OB_ZONES;
SELECT * FROM oceanbase.DBA_OB_UNITS;

第一步,定义一个 Unit 规格(MINI_MODE 内存有限,给小一点):

CREATE RESOURCE UNIT unit_s1
  MAX_CPU 1,
  MEMORY_SIZE '1G',
  MAX_IOPS 1000,
  MIN_IOPS 1000,
  LOG_DISK_SIZE '2G';

第二步,用这个 Unit 建一个 Resource Pool,指定落在哪个 zone:

CREATE RESOURCE POOL pool_mysql
  UNIT='unit_s1',
  UNIT_NUM=1,
  ZONE_LIST=('zone1');   -- 换成你 SHOW ZONES 看到的实际 zone 名

第三步,建租户,把池挂上,并声明兼容模式、可访问的 IP:

CREATE TENANT mysql_tenant
  RESOURCE_POOL_LIST=('pool_mysql'),
  PRIMARY_ZONE='zone1',
  LOCALITY='F@zone1'
  SET OB_COMPATIBILITY_MODE='MYSQL',
      OB_TCP_INVITED_NODES='%';

PRIMARY_ZONE 和 LOCALITY 后面讲高可用那篇会展开,这里先照着 zone 名填。OB_TCP_INVITED_NODES='%' 是放开连接白名单——不配这个,外部客户端连不进来,这是我的第二个坑。

建好之后,用租户身份连进去(user@tenant 这种写法):

obclient -h127.0.0.1 -P2881 -uroot@mysql_tenant -A

初始 root 没密码,记得改。然后就能像普通 MySQL 一样建库建表写数据了。

CREATE DATABASE shop;
USE shop;
CREATE TABLE item (id BIGINT PRIMARY KEY, name VARCHAR(64));
INSERT INTO item VALUES (1, 'keyboard');

3. 客户端怎么连:直连 vs OBProxy

单机体验时直接连 observer 的 2881 端口最省事。但到了生产,应该在前面架 OBProxy(也叫 ODP,OceanBase Database Proxy)。

OBProxy 是独立的接入层进程,兼容 MySQL 协议。它的活儿是:自动发现数据分布,把每条 SQL 路由到对应主副本所在的 OBServer;同时做连接管理、负载均衡。对应用来说,只管连 OBProxy 一个地址,完全不用关心数据到底在哪个节点。

为什么分布式下需要它?因为数据散在多台机器,你直连某一台 observer,碰到数据不在本地的 SQL,它得走”远程 / 分布式”计划去别的节点取——OBProxy 在前面帮你做路由和连接复用,省掉这些麻烦。

本地想试 OBProxy 的话,社区版有现成镜像(具体版本和端口以你拉的为准,默认代理端口通常是 2883):

docker run -p 2883:2883 -d oceanbase/obproxy-ce
# 之后应用就连 2883,写法不变:user@tenant
obclient -h127.0.0.1 -P2883 -uroot@mysql_tenant -A

生产上 OBProxy 一般部署多个、前面再挂一层负载均衡,避免它自己成单点。


4. 分区表:数据是怎么”散”出去的

这是分布式 SQL 的入门关键。单机库里一张表基本就是一个整体;在 OB 里,表会按分区拆成多个 Tablet,每个 Tablet 才是数据分布、复制、均衡的最小单位。

分区方式常见的有 Range(按范围)、Hash(按哈希)、List、Key,还能组合。它的意义有两层:

  • 水平扩展:单表再大也能拆开平摊到各 Zone 的 OBServer 上,不会卡在单机容量。
  • 分区剪裁:查询能只扫相关的 Tablet,不用全表扫。

举个例子,按用户 id 哈希分 8 个区:

CREATE TABLE orders (
  id BIGINT,
  user_id BIGINT,
  amount DECIMAL(10,2),
  PRIMARY KEY(id)
) PARTITION BY HASH(user_id) PARTITIONS 8;

我当初以为”建表跟 MySQL 一样写就行”,后来才懂:分区策略直接决定数据怎么分布、热点怎么打散、查询能不能剪裁——选错了,分布式反而比单机还慢。这块值得单独花时间琢磨。


5. 小结 & 下一步

  • OB 的资源模型是 Cluster → Tenant → DB → Table,中间 Unit / Pool 是资源载体;建业务租户要 Unit → Pool → Tenant 三步走。
  • 连数据库生产环境走 OBProxy 更省心,应用只认一个地址。
  • 分区表是数据分布的基础,分区策略直接影响性能和扩展能力。

下一篇讲高可用与弹性:把 Paxos 多数派、主副本、租约防脑裂讲透;再说 locality / primary_zone 怎么决定副本分布和 Leader 在哪;最后看看加节点扩容、一个 Zone 挂了到底会发生什么——这正好对应我们 K8s 上最该操心的容灾逻辑。

参考: