基于湖库一体架构,统一管理结构化、半结构化与非结构化等多模态数据,一个系统承载事务处理、实时分析与 AI 工作负载。
TableAPI 实现介绍
更新时间:2023-08-03 17:20:32
TableAPI 提供了对表模型数据的操作接口。同时,在内部,TableAPI 定义了客户端和数据库服务端之间的一组通用的交互协议。本文将对 TableAPI 的实现原理进行详细介绍。
TableAPI 流程
如图所示,TableAPI 由客户端、RPC 框架和服务端三部分组成。本文分别介绍下这三部分的作用。 
客户端
OceanBase 是分布式数据库,每个表甚至每个表的不同分区都可能存放在不同的机器上,而想要对表进行读写就必须先要定位到数据所属的表或是分区的位置。
特别的,对于 TableAPI,OBServer 当前并不会做路由转发,只在本地执行,路由错误会读写非预期的数据。因此每一轮操作,客户端都会先根据 table name、rowkey 算出具体的分区号 partition id,进而根据分区号计算得出执行该指令的 observer 具体位置,然后再把 request 请求发送到对应 observer 节点。
另外,客户端除了要保证基本的读写功能外,还承担着路由计算的重大使命。
RPC 框架
TableAPI 使用 OceanBase 数据库自定义的 RPC 协议进行通信,这个协议是标准的 Request-Response 模型。
不同的 Request 之间互相独立,Server 端会并发处理多个请求。同一个客户端和 Server 端之间可以建立多个 TCP 连接。这层模型由 libeasy 封装。
在 libeasy 的包内包含 OceanBase RPC 包的包头和数据。数据经过 RPC 层传递后到服务端后,需要再经过 decode 模块对数据包进行解析,server 最后从 pkg 请求包中解析出消息类型以及数据体。
服务端
OBServer 服务端使用生产者消费者模型来处理客户端的 TableAPI 消息请求。客户端并发消息的最大个数取决于队列的长度以及 server 的处理速度。
当服务端接收到客户端请求后,由独立线程把 request 消息放到消息队列中,并且由工作线程从队列中取出消息体并处理。
为了区分不同类型的消息,observer 采用优先级队列,对不同类型的消息(MYSQL,RPC 等)进行分层处理,这样可以保证某些优先级比较高的请求不会因为超时而被"饿死"。
另外,TableAPI 与 OceanBase SQL 采用相同的事务框架以及存储引擎。存储引擎是两级分区表 + LSM 树,两级分区表支持哈希分区、Range 分区、以及哈希和 Range 的各种组合,能够通过自动 range 分区和自动分区负载均衡来解决分区热点问题和机器热点问题,对用户完全透明。
说明
TableAPI 当前不支持跨分区事务。
TableAPI 操作类型
TableAPI 支持 login、execute、batch_execute 和 query(查询扫描)四种不同的操作类型。
操作类型的实现背后是分别使用四个不同的 Processor 类进行管理。每一种类型通过继承和派生衍生出对应的 process 处理函数,分别处理不同的 RPC 消息请求。

- 登录请求:ObTableLoginRequest,需要提供和 SQL 一样的 OceanBase 租户用户名和密码用于认证,认证成功才可以使用其他 TableAPI。
- TableAPI 单次处理请求:ObTableOperationRequest,例如 insert、update、replace、get、increment、append 等。
- TableAPI 批处理请求:ObTableBatchOperationRequest,单处理的集合。
- TableAPI 流式查询请求:ObTableQueryRequest,例如针对某 primary key 范围的 scan range。
各操作类型实现类图如下:

单处理(execute)
单处理在 OBServer 端的处理结果将以返回值 errno & 影响行数 affected_rows 的方式返回给客户端,表示操作的最终结果。
说明
下文中的 Insert、Get 等字样为操作行为,并非实际的函数或接口。
Insert
该操作的作用是插入一行记录。
该操作的返回结果分为以下几种:
- 插入成功,返回 errno 为 OB_SUCCESS,affected_rows 为 1。
- 插入失败,返回 affected_rows 为 0。
- 因为主键冲突(即这行已经存在)插入失败,返回 errno 为 OB_ERR_PRIMARY_KEY_DUPLICATE。
- 其他常见错误码:
- OB_TIMEOUT:执行超时。
- OB_TRY_LOCK_ROW_CONFLICT:等待行锁超时。
Get
该操作的作用是取回一行记录。
如果目标行存在,返回目标行记录,否则,返回为空。
Delete
该操作的作用是删除一行记录。
该操作的返回结果分为以下几种:
- 目标行记录被成功删除,返回 errno 为 OB_SUCCESS,affected_rows 为 1。
- 目标行不存在,返回 errno 为 OB_SUCCESS,affected_rows 为 0。
Update
该操作的作用是更新一行记录。
该操作的返回结果分为以下几种:
- 目标行记录被成功更新,返回 errno 为 OB_SUCCESS,affected_rows 为 1。
- 目标行不存在,返回 errno 为 OB_SUCCESS,affected_rows 为 0。
Insert_or_update
该操作的作用是插入或修改一行记录。
该操作的返回结果分为以下几种:
- 目标行不存在,则插入记录,成功后返回 errno 为 OB_SUCCESS,affected_rows 为 1。
- 目标行已经存在(即主键冲突),则更新该行记录,成功后返回 errno 为 OB_SUCCESS,affected_rows 为 1。
- 插入存在唯一索引冲突,则也执行更新操作。
Replace
该操作的作用是替换一行记录。
该操作的返回结果分为以下几种:
- 目标行不存在,则插入记录,成功后返回 errno 为 OB_SUCCESS,affected_rows 为 1。
- 目标行已经存在(即主键冲突),则删除原记录,然后再插入需替换的记录,成功后返回 errno 为 OB_SUCCESS,affected_rows 大于 1。
- 若存在唯一索引冲突,则删除所有引起冲突的行,然后再插入需替换的记录,成功后返回 errno 为 OB_SUCCESS,affected_rows 大于1(包含被删除的行)。
注意
replace 操作和 insert_or_update 操作很容易混淆,您可参考文档 replace 和 insert_or_update 的区别 对这两种操作进行区分。
Increment
该操作的作用是把指定列的值原子地增加某个增量值(可以为负数)。
该操作为 OceanBase 1.4.75 开始新增特性,支持操作整型列类型,含 tinyint、smallint、mediumint、int、bigint 及对应的无符号列类型,其他列类型报错。 该操作的返回结果分为以下几种:
- 如果计算结果溢出列类型的值域,则报错。
- 如果目标行不存在,则插入,把增量值设置为初值(即等价于原值为 0)。
- 如果目标行存在,但是指定列的值为 NULL,把增量值设置为初值(即等价于原值为 0)。
Append
该操作的作用是把指定列的值原子的追加某个串。
该操作为 OceanBase 1.4.75 开始新增特性,支持 varchar/varbinary 类型,其他列类型报错。 该操作的返回结果分为以下几种:
- 如果计算结果溢出列的长度,则报错。
- 如果目标行不存在,则插入,把增量值设置为初值(即等价于原值为空串)。
- 如果目标行存在,但是指定列的值为 NULL,把增量值设置为初值(即等价于原值为空串)。
批操作(batch operation)
批操作为单操作的合集,因此若想了解批处理的具体表现,您可以参考本文的 单处理(execute) 章节。
特别的,为了加速批操作流程,在针对只读批操作集合的处理上,OBServer 做了只读事务的优化,因此相比于读写批操作,只读批操作集合在性能上的表现会更好。
查询操作(query)
TableAPI 支持根据主键或主键的前缀进行范围扫描,也可以不指定主键,根据索引或索引前缀范围进行扫描查询。
Query 操作类型可以指定多段范围进行扫描。现阶段,在一次 Query 的 RPC 消息交互过程中,最大能从服务端返回 64M 的结果数据集合(可调整)。
关于 Query 各种条件的设置方式,可以参考 客户端简介与使用说明。
支持的值类型
TableAPI 支持 OceanBase SQL 支持的所有值类型。包括:
- NULL
- Tiny Int、Unsigned Tiny Int
- Small Int、Unsigned Small Int
- Medium Int、Unsigned Medium Int
- Int、Unsigned Int
- Big Int、Unsigned Big Int
- Float、Unsigned Float
- Double、Unsigned Double
- Decimal、 Unsigned Decimal
- Datetime、Timestamp
- Date、Time、Year
- Varchar、Char(支持两种 collation:utf8mb4_general_ci 和 utf8mb4_bin)
- Varbinary、Binary
- Tiny Text、Text、Medium Text、Long Text
- Tiny Blob、Blob、Medium Blob、Long Blob
- Bit