---
title: "主备租户自动路由与读写分离 - 数据库代理  V4.3.5 | OceanBase 文档中心"
description: 主备租户自动路由与读写分离 背景介绍 在 OceanBase 数据库 2.x 和 3.x 版本中，采用基于主备库的方法进行容灾管理，其 cluster_name 对应一组主备集群。用户登录时默认主集群登陆（cluster_id=0），如果登陆连接串中携带 cluster_id，可以标识主/备集群登录，而 cluste…
---
切换语言

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

文档反馈![](https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*nSAhQbrBXKwAAAAAAAAAAAAADiGDAQ/original) 数据库代理 V 4.3.5

# 主备租户自动路由与读写分离

更新时间：2025-11-21 11:17:54

[编辑](https://github.com/oceanbase/oceanbase-proxy-doc/edit/V4.3.5/zh-CN/600.data-routing/450.primary-and-backup-tenant-routing.md)  

## 背景介绍

在 OceanBase 数据库 2.x 和 3.x 版本中，采用基于主备库的方法进行容灾管理，其 cluster_name 对应一组主备集群。用户登录时默认主集群登陆（cluster_id=0），如果登陆连接串中携带 cluster_id，可以标识主/备集群登录，而 cluster_id 对应的主备关系通过 OCP 进行维护。

但随着 OceanBase 数据库架构的演进，自 4.1.0 版本起将主备的管理方式下放到租户级别，集群级不再有主备角色的概念，集群仅用于管理租户，集群名唯一标识一个集群，对两个不同租户，可以互为主备关系。同时，租户的主备关系将不在数据库中进行维护，数据库中的主备租户相互不记录对方身份，而是通过外部组件（OCP）进行记录维护。为了实现租户级主备的自动路由，OceanBase 数据库引入了服务的概念。一个服务下可以有多个同集群或跨集群的租户，用户在通过 ODP 连接数据库时，可以使用指定服务名的方式将连接自动路由到主租户。

## 技术原理

OceanBase 数据库中主备租户路由的基本框架如下图。用户通过特定的连接串登录 ODP，ODP 识别主备租户登录，通过向 OCP 获取相关的租户信息，完成自动路由到主租户，并发往对应的 OBServer 节点。OBServer 节点将校验对应的租户信息，校验通过后 ODP 进行建连，完成整个登录流程。

![原理](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/odp/V4.3.1/zh-CN/600.data-routing/450.primary-and-backup-tenant-routing-01.png)

## 使用说明

#### 注意

主备租户路由功能需 OCP、ODP、OceanBase 数据库三者配合使用，缺一不可。使用主备租户路由功能时，要求 OCP 需为 V4.3.1 或之后版本，ODP 需为 V4.3.1 或之后版本，OceanBase 数据库需为 V4.2.4 或之后的 V4.2.x 系列版本。

### Service Name

1. 创建服务

   OCP 白屏化创建主备租户时可提供一个服务名作为唯一标识主备租户的入口，被称为 **服务名**（即本文的 Service Name），服务名的详细介绍可参见官网《OceanBase 云平台》文档 [租户管理/管理租户/管理服务名](https://www.oceanbase.com/docs/common-ocp-1000000001740041)。
 2. Service Name 租户信息查看

   登录系统租户后，可执行如下命令查看集群中关联 Service Name 的所有租户：

   ```sql
   SELECT t.tenant_id, t.tenant_name
       FROM oceanbase.CDB_OB_SERVICES AS s JOIN DBA_OB_TENANTS AS t
       ON s.tenant_id = t.tenant_id WHERE s.service_name = "xxxx";

   ```

   如果 OCP 管理了数个集群，则每一个集群都要执行该查询命令。
 3. 通过 Service Name 登录主备租户

   主备租户的同名服务均设置成功，并且主备租户所属的集群已被 OCP 接管，同时主备租户所属的集群均关联至相同的 ODP（OBProxy）集群后，用户就可以通过指定服务名的方式来连接数据库，实现主备租户的自动路由。连接串如下：

   ```shell
   obclient -h<IP> -P<PORT> -u<USER_NAME>@SERVICE:<SERVICE_NAME> -p

   ```

   连接串的 `SERVICE:` 为关键字，需为其配置待登陆租户的服务名称，`<IP>` 和 `<PORT>` 需根据实际情况替换为 ODP 的 IP 地址和端口。

   #### 注意

   若正常使用 ODP 登录 OceanBase 集群时，所用用户名为 SERVICE（不区分大小写），ODP 会识别为主备租户登录，并将配置的 `cluster_name` 识别为待登录租户的服务名。

   #### 说明

   ODP V4.3.1 BP3 及之后的 4.3.1.x 版本，以及 V4.3.3 及之后版本中，增加 Service Name 的配置方式，可通过 `<USER_NAME>@SERVICE#<SERVICE_NAME>` 或 `<SERVICE_NAME>-SERVICE-<USER_NAME>` 格式指定服务名。

   以 ODP 的 IP 地址和端口分别为 `10.10.10.1` 和 `2883`，Service Name 为 `test` 为例，连接串如下：

   ```shell
   obclient -h10.10.10.1 -P2883 -uroot@SERVICE:test
   # 或
   obclient -h10.10.10.1 -P2883 -uroot@SERVICE#test
   # 或
   obclient -h10.10.10.1 -P2883 -utest-SERVICE-root

   ```

   使用 Service Name 登录后，ODP 将请求自动路由到 Service Name 绑定的主租户。一个 Service Name 可以对应多个租户。当数据库处于升级或迁移过程时，Service Name 路由提供无缝的应用程序连接，即使后端数据库发生了变化，服务名称可以保持不变。

### 自动路由

ODP 支持配置 Service Name 登录后，支持主租户的自动路由能力。具体如下：

- 路由重试：当后端发生 Switchover/Failover 时，ODP 根据协商的错误码，主动重试可用租户列表（支持跨集群重试）。切换到主租户重试时将不会返回错误，从而实现业务无感知的路由切换。

  需要注意的是，在以下类型的 SQL 请求中，ODP 不支持切换租户/重试请求，会返回 OceanBase 数据库的错误码：

     - 事务中路由：ODP 不会切换租户，依然将请求发往事务开启的租户。
     - 临时表路由：ODP 会发往上一个请求的节点。
     - 依赖上一条 SQL 的执行结果：如 `found_rows()`、`row_count()` 等函数，需要发往上一个请求的节点。
     - LOAD FILE 导数场景：不支持切换租户。
     - CURSOR/PIECES 场景：客户端使用 CURSOR/PIECES 流式获取/上传数据时，所有请求会强制路由到统一节点。
 - 自动找主：发生路由重试时，表示缓存的主租户信息错误，ODP 将根据租户列表，主动获取对应 OBServer 节点的租户角色，找到主租户并更新缓存信息。
 - 定时刷新：ODP 会间隔一段时间（由 [config_server_refresh_interval](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000003575533) 控制，默认 60s），更新 Service Name 相关路由信息，保证缓存信息不会落后太久。
 - 高可用：当用户使用 Service Name 登录后，ODP 会定时将缓存信息写入磁盘，在 OCP 不可用时仍然提供自动路由能力。

### 读写分离

ODP 自 V4.3.3 起支持对主备租户进行读写分离，由配置项 `enable_standby_read_write_split` 控制通过 Service Name 登录的租户是否开启主备租户读写分离功能。开启主备租户的读写分离后，ODP 会将非事务内的读请求路由到备租户，其他请求则路由到主租户。其中，对于发往 last session 的请求，会路由到上一个租户。

以开启 `service_name_a` 的主备租户读写分离能力为例，具体设置步骤如下。

#### 说明

开启读写分离后，如需进行租户内读写分离配置，可参见 [读写分离](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000003575301)。

1. 设置 `service_name_a` 的备集群为 `cluster_A`

   ```shell
   replace into proxy_config(cluster_name, tenant_name, name, value, config_level) values ('', 'service:service_name_a', 'rootservice_cluster_name', 'cluster_A', 'LEVEL_TENANT');

   ```

   通过 Service Name 登录时，`rootservice_cluster_name` 配置项用于设置读写分离场景下优先路由的备集群。配置租户级别时，租户名格式为 `service:xxxx`，集群名为空。`rootservice_cluster_name` 配置项的详细介绍可参见 [rootservice_cluster_name](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000003575571)。

   未配置 `rootservice_cluster_name` 的场景下，开启主备租户读写分离能力后，ODP 默认会将需要发给备租户的请求优先发给缓存中的第一个备租户。
 2. 开启 `service_name_a` 的主备租户读写分离能力

   ```shell
   replace into proxy_config(cluster_name, tenant_name, name, value, config_level) values ('', 'service:service_name_a', 'enable_standby_read_write_split', 'true', 'LEVEL_TENANT');

   ```

   配置租户级别时，租户名格式为 `service:xxxx`，集群名为空。`enable_standby_read_write_split` 配置项的详细介绍可参见 [enable_standby_read_write_split](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000003575573)。

   #### 说明

      - `enable_standby_read_write_split` 配置修改仅对新建连接生效，对已存在的连接不生效。
      - 若 ODP 无法获取备租户的 Service Name 信息，会将读写请求全部发送到主租户。

### 运维

您可通过如下两个配置项控制 Service Name 功能的使用：

- [enable_standby](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000003575504) 配置项控制是否开启主备租户路由能力。默认为 True，如果配置为 False，ODP 将不会使用 Service Name 路由能力。
 - [config_server_refresh_interval](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000003575533) 配置项控制 ODP 从 OCP 中获取 Config Server 信息的时间间隔，默认为 60s。Service Name 相关信息也使用此配置。

#### 说明

通过 Service Name 登录时不受 [enable_cloud_full_username](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000003575590) 和 [enable_full_username](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000003575525) 配置项影响。

当出现主备租户相关问题时，可查看 Service Name 租户缓存信息或错误码进行排查：

- 对通过 Service Name 登录的用户，在 ODP 安装目录下的 `etc` 目录下会生成缓存文件 `obproxy_service_name_info.json`，通过此文件可以排查 ODP 获取的 Service Name 转换是否正确。

  #### 说明

  ODP 内部统一将 Service Name 以小写格式保存。
 - 错误码 `OB_NOT_PRIMARY_TENANT(-4782)` 表示 SQL 请求发给了备租户，此时可能执行了 SwitchOver。
 - 错误码 `OB_SERVICE_NAME_NOT_FOUND(-4780)` 表示此 Service Name 在 OceanBase 数据库中不存在，此时 ODP 缓存信息可能过期。

 上一篇 下一篇 ![有帮助](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) 咨询热线
