---
title: "ODP 路由最佳实践 - OceanBase 最佳实践 | OceanBase 文档中心"
description: ODP 路由最佳实践 OceanBase 数据库代理（OceanBase Database Proxy，简称 ODP，又称 OBProxy）是 OceanBase 数据库专用的代理服务器，使用 ODP 可以屏蔽后端 OceanBase 集群分布式带来的复杂性，让访问分布式数据库像访问单机数据库一样简单。 ODP 的核…
image: https://mdn.alipayobjects.com/huamei_22khvb/afts/img/A*OSPzQ6GUQF4AAAAAQHAAAAgAeiGDAQ/original
---
切换语言

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

# ODP 路由最佳实践

更新时间：2026-07-28

[编辑](https://github.com/oceanbase/best-practices-doc/edit/master/zh-CN/500.route/7800.odp_routing_best_practices.md) 适用产品： OceanBase 数据库 适用场景： 路由  

OceanBase 数据库代理（OceanBase Database Proxy，简称 ODP，又称 OBProxy）是 OceanBase 数据库专用的代理服务器，使用 ODP 可以屏蔽后端 OceanBase 集群分布式带来的复杂性，让访问分布式数据库像访问单机数据库一样简单。

ODP 的核心特性是最佳路由，基本逻辑是 ODP 接收用户发出的 SQL 请求，并将 SQL 请求转发至最佳目标 OBServer 节点，最后将执行结果返回给用户。ODP 支持丰富的路由功能，以满足用户在不同场景下的路由需求，实现最佳路由效果。本文主要介绍常用的路由功能及配置方式，帮助用户在业务实践中正确配置路由策略及快速排查路由问题。

## 常用路由功能与配置

ODP 提供了丰富的路由功能，用户可以根据实际需要，设置对应的配置项来控制路由策略。

### 强制路由

强制路由是指用户无法控制的路由行为，由 ODP 决定是否强制路由，主要包含以下情况：

- 指定 IP 路由：可通过 `target_db_server` 配置项进行指定，ODP 会将 SQL 请求直接路由到指定的 OBServer 节点，此方式具有最高优先级。示例如下：

  ```shell
  ALTER PROXYCONFIG SET target_db_server = '127.0.0.1:2993;10.10.10.1:50109';

  ```

  上述示例中， ODP 收到的所有请求都会路由到 127.0.0.1:2993 节点。如果 127.0.0.1:2993 节点不存在或者故障，则路由到 10.10.10.1:50109 节点。关于指定 IP 路由的更多信息，请参考 [指定 IP 路由](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000000755689)。
 - 指定 Zone 路由：可通过 `proxy_primary_zone_name` 配置项进行指定，ODP 会将请求直接路由到指定的 Zone。示例如下：

  ```shell
  ALTER PROXYCONFIG SET proxy_primary_zone_name='z2';

  ```

  上述示例中，ODP 收到的所有请求都会路由到 z2。关于指定 Zone 路由的更多信息，请参考 [强读 Primary Zone 路由](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000000755698)。
 - 特定场景强制路由：

     - 非分布式事务路由：事务内语句强制路由至事务开启的 OBServer 节点。
     - 会话级临时表路由：对会话级临时表进行查询时，会强制路由至第一次查询临时表的 OBServer 节点。
     - CURSOR/PIECES 路由：客户端使用 CURSOR/PIECES 流式获取/上传数据时，所有请求会强制路由至同一 OBServer 节点。

#### 说明

- 指定 IP 路由和指定 Zone 路由，是强制性的路由，不会区分是否强读，适用于不关心 Leader 位置，需要路由到指定节点的场景。
 - 如果是交易支付等强读业务，希望路由到 Leader 的场景，需要确保强制路由配置项没有设置，避免产生大量远程路由、二次路由等问题。

### 强读路由

强读路由主要分为以下情况：

- 分区表路由：ODP 将 SQL 请求中的分区键值或表达式、分区名等条件解析为分区 ID，通过分区 ID 查找到分区的副本位置，将请求路由到 Leader 副本。

     - 根据分区键值或表达式计算路由，示例如下：

      ```shell
      CREATE TABLE T(C1 INT) PARTITION BY HASH(C1) PARTITIONS 8；

      SELECT * FROM T WHERE C1=123;
      SELECT * FROM T WHERE C1=ABS(123);

      ```

      上述示例中，ODP 将查询请求路由到对应分区 Leader 节点。
     - 根据分区名计算路由，示例如下：

      ```shell
      CREATE TABLE T(C1 INT) PARTITION BY KEY(C1) PARTITIONS 8;

      SELECT * FROM T PARTITION(P1);

      ```

      上述示例中，ODP 将查询请求路由到 P1 分区的 Leader 节点。  

  #### 说明

     - OceanBase 数据库有 Local 计划、Remote 计划和 Distributed 计划三种表路由。
     - Local 计划、Remote 计划均为单分区的路由。ODP 的作用是尽量消除 Remote 计划，将路由尽可能的变为 Local 计划。
     - 如果表路由类型为 Remote 计划的 SQL 过多，说明该 ODP 的路由可能存在问题，需要排查。  

  关于分区表路由的更多信息，请参考 [强读分区表路由](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000000755693)。
 - 全局索引表路由：使用全局索引表路由时，ODP 会将 SQL 语句中提供的索引值作为分区键来计算路由。强读分区表时，在为分区表创建全局索引，并在后续的读写中使用索引值作为查询条件的情况下，可使用 ODP 的全局索引路由功能来提升查询效率。

  可通过配置 `enable_reroute` 和 `enable_index_route`，将语句中提供的索引值作为分区键来计算路由，示例如下：

  ```shell
  ALTER PROXYCONFIG SET enable_reroute=true;
  ALTER PROXYCONFIG SET enable_index_route = true;

  CREATE TABLE T(C1 INT,C2 INT) PARTITION BY HASH(C1) PARTITIONS 8；
  CREATE INDEX INDEX1 ON T(C2);

  SELECT * FROM T WHERE C2=2;
  SELECT * FROM T WHERE C2=2;

  ```

  上述示例中，第一次使用索引查询，将随机路由，OBServer 节点将返回索引表的 Leader，ODP 会构建语句到索引表名称 [SELECT * FROM T WHERE C2=2;] -> [T_INDEX] 的映射然后进行二次路由，直接获取 `T_INDEX` 表的映射，计算路由。

  关于全局索引表路由的更多信息，请参考 [强读全局索引表路由](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000000755695)。
 - 复制表路由：复制表是 OceanBase 数据库中的一种特殊表结构，支持在任意一个副本读取数据的最新修改，适合于对写入频率要求较低，读延时和读负载均衡要求较高的场景。

  ODP 对复制表采用随机路由的策略，示例如下：

  ```shell
  CREATE TABLE T_DUP(C1 INT) DUPLICATE_SCOPE = 'cluster';

  SELECT * FROM T_DUP WHERE C1=123;

  ```

  上述示例中，ODP 将查询请求随机路由到 `T_DUP` 表的任意副本。关于复制表路由的更多信息，请参考 [强读复制表路由](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000000755690)。
 - 计算失败后的路由：当 ODP 无法获取 SQL 请求中的表名或者无法通过 SQL 请求中的条件计算出准确的分区位置信息时，无法准确的强读请求路由到 Leader。此时有三种处理策略：

     - 按照租户 Primary Zone 路由：`enable_primary_zone=True`，将请求路由到租户的 Primary Zone。
     - 复用上一次的会话路由：`enable_cached_server =true`，将请求路由到上一个OBServer 会话。
     - 随机路由：`enable_primary_zone=false` 且 `enable_cached_server =false`，将请求随机路由。

  示例如下：

  场景一：enable_primary_zone=false && enable_cached_server =true

  ```shell
  CREATE TABLE T(C1 INT,C2 INT) PARTITION BY HASH(C1) PARTITIONS 8；

  SELECT * FROM T WHERE C1=1; # 请求准确路由到 server1
  SELECT * FROM T WHERE C2=1; # 无分区条件，无法计算路由，直接将请求路由到上一个会话 server1

  SELECT * FROM T WHERE C1=2; # 请求准确路由到 server2
  SELECT * FROM T WHERE C2=2; # 无分区条件，无法计算路由，直接将请求路由到上一个会话 server2

  ```

  场景二：enable_primary_zone=true && enable_cached_server =true && leader在server1

  ```shell
  SELECT * FROM T WHERE C1=1; # 请求准确路由到 server1
  SELECT * FROM T WHERE C2=1; # 无分区条件，无法计算路由，直接将请求路由到 server1

  SELECT * FROM T WHERE C1=2; # 请求准确路由到 server1
  SELECT * FROM T WHERE C2=2; # 无分区条件，无法计算路由，直接将请求路由到server1

  ```

  #### 说明

  对于生产环境和测试环境，一般情况下，建议 `enable_cached_server` 设置为 `false`。

  如果需要分析 ODP 的路由策略，可以使用 `EXPLAIN ROUTE executable sql` 查看 ODP 路由选取过程。

### 事务路由

事务路由分两种场景：

- 分布式事务路由：事务内的 SQL 请求准确路由到 Leader 节点。

  #### 说明

  OceanBase 数据库 V4.1.0 版本开始支持分布式事务路由。

  可通过配置 `enable_ob_protocol_v2 = true` 和 `enable_transaction_INTernal_routing = true` 来开启分布式路由，示例如下：

  ```shell
  ALTER PROXYCONFIG SET enable_ob_protocol_v2 = true;
  ALTER PROXYCONFIG SET enable_transaction_INTernal_routing = true;

  CREATE TABLE T1(C1 INT,C2 INT) PARTITION BY HASH(C1) PARTITIONS 8；
  CREATE TABLE T2(C1 INT,C2 INT) PARTITION BY HASH(C1) PARTITIONS 8；

  BEGIN;
  INSERT INTO T1 VALUES(1,1);# 路由到server1
  INSERT INTO T2 VALUES(11,11);# 路由到server2
  SELECT * FROM T1 WHERE C1=1;# 路由到server1
  SELECT * FROM T2 WHERE C1=11;# 路由到server2
  COMMIT;

  ```

  上述示例中，事务内的请求都能够准确路由到对应的 Leader。关于分布式路由的更多信息，请参考 [分布式事务路由](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000000755691)。
 - 非分布式事务路由：事务内 SQL 请求强制路由至事务开启 OBServer 节点。

  示例如下：

  ```shell
  ALTER PROXYCONFIG SET enable_ob_protocol_v2 = false;
  ALTER PROXYCONFIG SET enable_transaction_INTernal_routing = false;

  BEGIN;
  INSERT INTO T1 VALUES(1,1);# 路由到server1
  INSERT INTO T2 VALUES(11,11);# 路由到server1
  SELECT * FROM T1 WHERE C1=1;# 路由到server1
  SELECT * FROM T2 WHERE C1=11;# 路由到server1
  COMMIT;

  ```

  上述示例中，事务内的请求都路由到第一条 INSERT 的路由节点 server1。

### 弱读路由

对于弱读请求，ODP 提供两种路由策略：

- LDC 路由：给 OceanBase 集群的每个 Zone 设置地区（Region）属性和机房（IDC）属性，并给 ODP 指定机房（IDC）配置项，ODP 将弱读请求按“同机房>同地区>异地”的优先级顺序进行 OBServer 节点的选取。

  可通过配置项 `proxy_idc_name` 控制 LDC 路由，示例如下：

  ```shell
  alter system modify zone "z1" set region = "region1";
  alter system modify zone "z1" set idc = "idc1";

  alter system modify zone "z2" set region = "region1";
  alter system modify zone "z2" set idc = "idc2";

  alter proxyconfig set proxy_idc_name='idc1';

  CREATE TABLE T(C1 INT,C2 INT) PARTITION BY HASH(C1) PARTITIONS 8；
  SELECT /*+READ_CONSISTENCY(WEAK) */ * FROM T;

  ```

  上述示例中，ODP 会将弱读请求路由到同 IDC 的 `z1`。
 - 随机路由：ODP 将弱读请求随机路由到 Leader 或者 Follower 副本，副本优先级由 `proxy_route_policy` 控制。对应路由策略为：`FOLLOWER_FIRST`、`FOLLOWER_ONLY`、`UNMERGE_FOLLOWER_FIRST`。

  本文内容以 ODP V4.3.0 为例，示例如下：

  ```shell
  CREATE TABLE T(C1 INT,C2 INT) PARTITION BY HASH(C1) PARTITIONS 8；
  # T 表的 leader 在 z1，follower 在 z2、z3

  ```

  场景一：alter proxyconfig set proxy_route_policy='';

  ```shell
  SELECT /*+READ_CONSISTENCY(WEAK) */ * FROM T;
  # ODP 在 z1、z2、z3 三个副本随机选择副本转发弱读请求

  ```

  场景二：alter proxyconfig set proxy_route_policy='FOLLOWER_FIRST';

  ```shell
  SELECT /*+READ_CONSISTENCY(WEAK) */ * FROM T;
  # ODP 优先选择 z2、z3 转发弱读请求，如果 z2、z3 都不可用，则转发到 z1

  ```

  场景三：alter proxyconfig set proxy_route_policy='FOLLOWER_ONLY';

  ```shell
  SELECT /*+READ_CONSISTENCY(WEAK) */ * FROM T;
  # ODP 只选择 z2、z3 转发弱读请求，如果 z2、z3 都不可用，则请求报错

  ```

  场景四：alter proxyconfig set proxy_route_policy='UNMERGE_FOLLOWER_FIRST';

  ```shell
  SELECT /*+READ_CONSISTENCY(WEAK) */ * FROM T;
  # ODP 优先选择没在做合并的 z2、z3 转发弱读请求

  ```

  LDC 路由的优先级高于随机路由，ODP 在选择副本时，先检查 LDC 路由，再走随机路由策略。

  #### 说明

  弱读的路由策略 LDC 路由和随机路由，同样适用于计算分区失败的强读路由请求。

## 典型场景

在不同的业务场景，需要综合考虑路由策略配置及优先级，进行合理配置，实现指定的路由目标。下面以两个典型路由场景为例，介绍路由功能的应用实践。

### 读写分离

- 路由场景

  OLTP 与 OLAP 业务混合负载场景下，希望将交易类请求发送到 TP 副本，将分析型请求发送到 AP 副本，TP、AP 类业务请求需要部署独立的 ODP，接收 AP 请求的 ODP 需要支持将业务的强读请求转换为弱读，并只发送到 AP 副本。部署架构如图：

  ![部署架构](https://obbusiness-private.oss-cn-shanghai.aliyuncs.com/doc/img/best_practices/odp.png)
 - 路由配置实践

     - 接收 AP 请求的 ODP：

      ```shell
      alter proxyconfig set obproxy_read_consistency='1'; # 设置弱读

      alter proxyconfig set proxy_primary_zone_name='zone_4'; # 设置路由目标副本

      ```

      #### 注意

      设置之前，需确保没有设置过指定 IP 路由的配置。可通过 `show proxyconfig like 'target_db_server';` 命令进行检查。
     - 接受 TP 请求的 ODP：

      ```shell
      ALTER PROXYCONFIG SET enable_cached_server = false;
      ALTER PROXYCONFIG SET enable_primary_zone = true;

      ```

      对交易类请求，需要准确路由到分区 Leader，如果无法准确计算，则尽量路由到租户的 Primary Zone，减少远程路由。

      ODP 将交易类请求只发往 ZONE_1、ZONE_2、ZONE_3 的对应 Leader 副本。

      #### 注意

      设置之前，需确保没有设置过指定 IP 路由及指定 Zone 路由。可通过 `show proxyconfig like 'target_db_server';` 和 `show proxyconfig like 'proxy_primary_zone_name';` 命令进行检查。

### 只读副本

- 路由场景：

  OceanBase 数据库支持的副本类型，除了全功能型副本，还有只读型副本，简称 R 副本。R 副本只提供读能力，只能作为日志流的 Follower 副本。实际业务中，可以将实时性要求不高的分析类读请求发送到R副本，减轻 Leader 副本的压力。
 - 路由配置实践：

     - 设置弱读：`alter proxyconfig set obproxy_read_consistency='1';`
     - 设置 LDC 策略：只读副本同 IDC 的 ODP 和 OBServer 节点设置为相同 IDC。
     - 设置路由策略：`alter proxyconfig set proxy_route_policy='FOLLOWER_ONLY';`

## 案例分析

某云客户在使用 OceanBase 数据库时，通过租户的只读地址执行了一项大规模查询操作，但该查询操作并未按照预期访问到只读副本，而是访问到了主副本，影响了主副本的正常业务运行。

### 原因分析

经排查，发现在 OceanBase 数据库的路由配置中，启用了两个关键参数： `enable_cached_server` 和 `enable_primary_zone`。

当 `enable_primary_zone` 和 `enable_cached_server` 设置为 `true` 时，路由逻辑如下：

- `enable_primary_zone=true`：用户登录时，会将登录请求发往租户的主副本。
 - `enable_cached_server=true`: 在 ODP 没有解析出表名、表分区计算失败等情况下，请求会复用前一个连接，也就是登录时选择的主副本，这就导致请求无法根据只读地址信息对路由做优化，造成后续的所有请求都发往了主副本。

### 解决方法

关闭 `enable_cached_server` 和 `enable_primary_zone`。

## 相关文档

关于 ODP 路由的更多信息，请参考 [ODP 路由功能](https://www.oceanbase.com/docs/common-odp-doc-cn-1000000000755434)。

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