首批通过分布式安全可靠测评,为关键业务系统打造
连接管理
更新时间:2026-04-14 09:41:07
ODP 为用户提供了数据库接入和路由功能,通过连接 ODP 就可以正常使用 OceanBase 数据库。用户在使用数据库功能时,ODP 和 OBServer 节点进行交互,且交互流程对用户透明,连接管理就是该交互过程中的关键点之一。
ODP 的连接管理有以下三个特性:
代理特性:ODP 既是客户端,也是服务端,还需要保证交互行为符合 MySQL 协议规范。
功能特性:ODP 实现了很多连接功能特性,如访问不同集群、不同租户,支持主备库、分布式下的 PS 功能,以及兼容 kill、show processlist 命令等。
高可用特性:ODP 可以处理超时、机器状态变化、网络状态变化等问题,屏蔽后端异常,让用户无感知。
接下来本文将按使用 ODP 的操作步骤一步一步讲解连接管理内容。
第一步:用户登录
登录信息
在登录 ODP 时需要填写数据库 IP 和 PORT、用户名、密码等信息。对于用户名,OceanBase 数据库的格式为 user_name@tenant_name,同时因为 ODP 可以代理不同的集群,所以格式又变为 user_name@tenant_name#cluster_name,字段含义如下:
user_name:登录的用户名,密码保存在 OceanBase 数据库中,ODP 只做登录报文转发不做密码校验。tenant_name:OceanBase 数据库是多租户架构,tenant_name 表示访问的租户名。cluster_name:集群名,ODP 支持访问多个集群,不同集群通过 cluster_name 区分。
有了这些信息就可以通过 JDBC 驱动、MySQL 命令行、Navicat 等工具连接 ODP 访问数据库了。
那么用户登录时 ODP 如何找到对应的机器呢?
如果是通过 rslist 方式启动 ODP,直接通过配置的 rs_list 即可找到对应的机器。但需注意,使用该方式只能连接一个集群。
如果是通过配置
obproxy_config_server_url启动,就要依赖 OCP 系统(通过obproxy_config_server_url配置项指定 OCP 的 url 地址访问),OCP 会保存集群名和集群的机器列表,ODP 通过访问 OCP 获取这些信息,整个流程如下图。
登录认证
找到机器后就进入到登录认证环节,关键信息是用户名和密码,MySQL 协议中(官方图片中展示了 Handshake 相关报文,实际流程中第 2 步结束后服务端需要回复一个 OK 或者 Error 报文给客户端)的交互流程如下图。

ODP 作为代理组件,要兼容 MySQL 和 Oracle 行为,会有更多步骤。此处以 Java 程序连接数据库为例说明整个流程,在 Java 程序中,登录代码只有一行:
conn = (Connection) DriverManager.getConnection(URL, USER_NAME, PASSWORD);
但背后的原理比较复杂,如下图所示:

在完成协议的登录步骤(第 8 步)后,协议层的登录交互就结束了,但 JDBC 会发送一些初始化 SQL,这也属于登录过程的一部分,图中第 9 步表示该过程。初始化 SQL 有多条,内容如下:
set autocommit=1, sql_mode = concat(@@sql_mode,',STRICT_TRANS_TABLES')
set names utf8
SELECT @@max_allowed_packet,@@system_time_zone,@@time_zone,@@auto_increment_increment,@@tx_isolation AS tx_isolation,@@session.tx_read_only AS tx_read_only
select @@version_comment, @@version limit 1
上面 SQL 执行完成后,Java 程序就可以发送业务 SQL 了。
常见登录问题
在明白 ODP 的登录原理之后就可以在登录失败时快速地定位和解决问题。常见的问题及原因如下:
用户名或密码错误,可以通过直连 OBServer 节点确定。
OCP 故障,无法拉取集群机器列表,可以通过 curl 命令访问 OCP 的 url 确定。
OBServer 节点执行获取机器列表或初始化 SQL 失败,需要日志排查定位。
超过最大连接数设置或需连接的 OBServer 节点不在白名单中。
对于上述问题,你可以通过查看 obproxy_error.log 方式解决。详细情况请参考 监控日志说明。
第二步:连接管理
登录成功后,客户端到 ODP、ODP 到 OBServer 节点之间的网络连接便建立了起来,此时 ODP 只是和其中一台 OBServer 节点建立了连接。随着 SQL 请求的到来,如果该请求被路由到新的 OBServer 节点,ODP 会和新的 OBServer 节点建立连接。在此过程中涉及连接的映射关系、状态同步和连接功能特性。
连接的映射关系
连接映射主要讲客户端连接和服务端连接之间的关系,首先从客户端连接说起。
当客户端和 ODP 建立一个连接后,ODP 会和后面 N 个 OBServer 节点建立连接,整个关系如下图所示:

从图中可以看到,ODP 按需和两台 OBServer 节点建立了连接,这两个连接只属于这一个客户端连接,不会被其他客户端连接复用。连接映射的关键点就是需要用 ID 标识出每一个连接并记录 ID 之间的映射关系。这样就可以用 proxy_sessid 唯一标识 App 和 ODP 之间的连接,用 server_sessid 唯一标识 ODP 和 OBServer 节点之间的连接。
当出现 SQL 执行错误、执行慢等情况时,ODP 会将映射关系打印到日志中,这样就可以将 App 和 OBServer 节点关联起来,进行全链路问题定位。
状态同步
一个客户端连接对应多个服务端连接,要保证执行结果的正确性,就要求多个服务端连接的 session 状态是一致的。
接下来举例说明 session 状态不同步将会导致什么问题,假设用户执行以下 SQL 命令:
set autocommit=1;
insert into t1 values(1);
insert into t2 values(2);
执行过程如下:
set autocommit=1发给 OBServer1 节点insert into t1 values(1)发给 OBServer1 节点进行连接切换,
insert into t2 values(2)发给 OBServer2 节点

对于第三条 SQL,ODP 和 OBServer2 节点的连接并未同步连接状态 autocommit=1,这样就可能导致第三条语句 insert into t2 并未提交事务。
正确的步骤是 ODP 在给 OBServer2 节点发送 INSERT SQL 前,先同步 autocommit 变量的值。ODP 通过版本号机制解决了状态同步的问题,实现了 database、session variables、last_insert_id 和 ps prepare 语句的状态同步,保证功能的正确性。
连接功能特性
和单机数据库不同,ODP 将连接的映射关系改变为 M:N,因此有些连接功能需要做额外处理。
举例说明:用户通过 show processlist 查看连接数,此时希望看到的是客户端和 ODP 之间的连接数,而不是 ODP 和 OBServer 节点之间的连接数。
下面我们对常见的连接功能展开详细介绍。
连接粘性
ODP 还未实现所有功能的状态同步,如事务状态、临时表状态、cursor 状态等。对于这些功能,ODP 只会将后续请求都发往状态开始的节点,这样就不需要进行状态同步,而缺点是无法充分发挥分布式系统的优势。因此,ODP 将根据功能重要程度,逐步支持相关功能的分布式化。
show processlist 和 kill 命令配套使用
show processlist 用于展示客户端和服务端之间的连接,对于 ODP 来说,show processlist 只展示客户端和 ODP 之间的连接,不展示 ODP 和 OBServer 节点之间的连接。
kill 命令用于杀死一个客户端连接,客户端连接关闭后,ODP 也会关闭对应的服务端连接。对于 ODP 的 kill 命令,需要先获取对应的 ID(使用 show processlist 命令即可获取 ID)。
负载均衡影响
因为 ODP 对 show processlist 和 kill 命令做了处理,所以 show processlist 和 kill 命令只有都发往同一台 ODP 才能正常工作。
在公有云等环境,ODP 前面有负载均衡,负载均衡后面挂在多个 ODP 上,此时,如果执行 show prcesslist 和 kill 命令是两个不同的连接,负载均衡组件可能将请求发往不同的 ODP,在这种情况下,建议不要使用相关命令。