适用版本:OceanBase 4.x + ODP 4.x。本文结论均基于 OB 4.2.5 / ODP 4.3.x 行为整理。
一、什么是弱读
弱读(弱一致性读):读请求可以走备副本,允许读到的数据不是最新的,但保证版本单调递增(不会越读越旧),同时把压力从主副本分摊到备副本。
| 对比项 | 强读 (STRONG) | 弱读 (WEAK) |
|---|---|---|
| 读哪个副本 | leader | 备副本(follower) |
| 数据新鲜度 | 保证最新已提交 | 允许滞后,但版本单调递增 |
| 主副本压力 | 全部在 leader | 分散到备副本 |
| 典型场景 | 交易、实时业务 | 报表、历史查询、对延迟不敏感的业务 |
注意:集群没有备副本时,弱读请求仍会落到 leader。
二、弱读的两种路由策略
弱一致性读有两种路由策略,读写分离和LDC路由。其中LDC路由的优先级高于读写分离,ODP在选择副本的时候,先检查LDC路由,再走读写分离路由。
2.1 读写分离
设置路由策略
某些场景下,我们希望将分析型的查询请求发送到从副本执行,此时就可以使用读写分离路由策略,通过将读请求发送到备副本,降低主副本的压力。
ODP通过配置项 proxy_route_policy 设置路由策略:
- follower_first:弱读请求优先路由到备副本,如果备副本都不可用,弱读请求路由到主副本。
- follower_only:弱读请求路由到备副本,如果备副本都不可用,断开和客户端的连接。
场景一
# 路由策略
alter proxyconfig set proxy_route_policy='';
# ODP 在z1、z2、z3 三个副本随机选择副本转发弱读请求
SELECT /*+READ_CONSISTENCY(WEAK) */ * FROM T; # primary zone1;zone2,zone3
场景二
# 路由策略
alter proxyconfig set proxy_route_policy='FOLLOWER_FIRST';
# ODP 优先选择z2、z3 转发弱读请求,如果z2、z3都不可用,则转发到z1
SELECT /*+READ_CONSISTENCY(WEAK) */ * FROM T;
场景三
# 路由策略
alter proxyconfig set proxy_route_policy='FOLLOWER_ONLY';
# ODP 只选择z2、z3 转发弱读请求,如果z2、z3都不可用,则请求报错
SELECT /*+READ_CONSISTENCY(WEAK) */ * FROM T;
2.2 LDC路由
OceanBase 数据库作为典型的高可用分布式关系型数据库,使用 Paxos 协议进行日志同步,天然支持多地多中心的部署方式以提供高可靠的容灾保证。但当采用多地多中心的部署架构时,弱一致性读会均匀访问数据的所有主从副本,当访问非本地域机房上的副本时,系统响应时间将大大增加。
引入逻辑数据中心(Logical Data Center,LDC)路由正是为了解决这一问题,通过给 OceanBase 集群的每个 Zone 设置 Region 属性和IDC 属性,并给 ODP 指定 IDC 名称配置项后,当数据请求发到 ODP 时,ODP将弱读请求按“同机房>同地区>异地”的优先级顺序进行OBServer 的选取。
- LDC的路由设置需要三个步骤:配置 OceanBase 集群、配置 ODP、应用配置弱一致性读。

1> OB集群LDC配置
- 使用 root 用户登录集群的 sys 租户
- 登录后,执行以下示例语句配置 LDC
ALTER SYSTEM MODIFY zone "zone1" SET region = "Shanghai";
ALTER SYSTEM MODIFY zone "zone1" SET idc = "Jiading";
ALTER SYSTEM MODIFY zone "zone2" SET region = "Zhejiang";
ALTER SYSTEM MODIFY zone "zone2" SET idc = "Hangzhou";
ALTER SYSTEM MODIFY zone "zone3" SET region = "Shanghai";
ALTER SYSTEM MODIFY zone "zone3" SET idc = "Waigaoqiao";
集群节点与LDC配置信息示例
| OBServer 节点 IP | Zone | IDC | Region |
|---|---|---|---|
| 10.0.0.1 | zone1 | Jiading | Shanghai |
| 10.0.0.2 | zone2 | Hangzhou | Zhejiang |
| 10.0.0.3 | zone3 | Waigaoqiao | Shanghai |
- 检查 OBServer 节点中 LDC 设置内容是否生效
select * from dba_ob_zones;
2> ODP的LDC配置
通过配置 proxy_idc_name 指定 ODP 在 LDC 逻辑中所处的位置。
- sys租户登陆,修改ODP的proxy_idc_name配置
ALTER PROXYCONFIG SET proxy_idc_name= 'Hangzhou';
- 为 ODP 配置 LDC 后可通过下述语句检查配置是否生效。
SHOW PROXYINFO IDC;
2.3 最佳实践
在odp上操作
# 第1步:开启弱读
ALTER PROXYCONFIG SET obproxy_read_consistency = 1;
# 第2步:设置路由策略。 在允许弱读的前提下,优先Follower节点
ALTER PROXYCONFIG SET proxy_route_policy = 'follower_first';
# 第3步:proxy_idc_name 参数决定就近范围,路由时优先选本机房的observer follower副本。前提条件:observer已配置IDC机房信息。
alter PROXYCONFIG set proxy_idc_name = 'Hangzhou'; # odp所在机房
注意:
在 ODP 架构下,当ODP开启弱读后,即使把 observer 全局参数 ob_read_consistency 改成 STRONG,请求不会因此路由到leader副本,ODP 路由按自己的判断发备follower副本。而observer全局参数 ob_read_consistency 主要用于observer直连场景。
三、弱读怎么配,优先级规则?
以上讲了 ODP 架构的弱读配置,但实际场景里大家还会遇到 hint、会话变量、ODP、Observer 甚至 OMS 里的弱读配置,它们各自管什么、怎么配、优先级谁高谁低,一直困扰不少人,下面是我的一些总结,希望帮助到你。
3.1 不同客户端的弱读配置
| 方式 | 配置位置 | 生效范围 | 适用场景 |
|---|---|---|---|
| SQL hint | SQL 语句内 | 单条语句 | 精准控制、临时验证 |
| 会话变量 ob_read_consistency=2 | 客户端 SET / JDBC 连接参数 | 单个连接 | 按连接分流 |
| ODP 参数 obproxy_read_consistency=1 | OCP 修改代理参数 ALTER PROXYCONFIG | ODP 上所有新老会话 | 全局弱读(推荐) |
| observer 全局 ob_read_consistency | ALTER SYSTEM SET | 内核执行语义 | 仅直连 observer 场景 |
3.2 使用示例
示例 1:单条 SQL 弱读(hint,最高优先级)
SELECT /*+ READ_CONSISTENCY(WEAK) */ * FROM orders WHERE user_id = 1001;
示例 2:当前连接弱读(会话变量)
SET ob_read_consistency = 2; -- 1=FROZEN, 2=WEAK, 3=STRONG
示例 3:JDBC 连接池级别弱读
jdbc:oceanbase://10.0.0.1:2883/mydb?sessionVariables=ob_read_consistency=2
示例 4:整个 ODP 弱读(推荐)
-- 以 root@proxysys 连接 ODP 执行,或在 OCP 的代理参数中修改
ALTER PROXYCONFIG SET obproxy_read_consistency = 1; -- 1=follower 弱读,0=leader(默认)
示例 5:直连 observer 场景(无 ODP)
ALTER SYSTEM SET ob_read_consistency = 'WEAK'; -- 全局;主要影响新会话
验证弱读是否生效(两条路)
- ODP 日志关键字:
current use weak read(需相应日志级别) - OCP
3.3 优先级规则
优先级从高到低:
| 层级 | 来源 | 说明 |
|---|---|---|
| 1 | SQL hint /*+ READ_CONSISTENCY(WEAK) */ |
最高 |
| 2 | 客户端会话变量(SET / JDBC sessionVariables) | 连接级;ODP 参数不变时不会被覆盖 |
| 3 | ODP 参数 obproxy_read_consistency |
连接时自动注入为会话变量(1→WEAK);参数变更时重新注入、反压客户端设置 |
| 4 | observer 全局变量 ob_read_consistency |
直连场景的主开关;ODP 架构下不参与路由 |
| 说明: |
- 优先级上,一般情况客户端高于 ODP;但运维在 OCP 改了 obproxy_read_consistency 后,ODP 会重新注入并覆盖客户端已 SET 的值。
- ODP 参数变更后(OCP 修改),存量连接无需重连:配置同步完成后,下一个请求自动生效。
ODP 弱读参数的内部转换规则如下:
# ODP弱读参数在会话建连时转换规则
obproxy_read_consistency=1
'1 表示follower,自动注入会话变量:SET ob_read_consistency=2(WEAK)'
obproxy_read_consistency=0
'0 表示leader(默认值),自动注入会话变量:SET ob_read_consistency=3(STRONG)'
四、避坑指南
1. 读写分离兜底陷阱
ODP 打开 enable_read_write_split=true 之后(默认 false),非事务里的 SELECT 只要没写 hint STRONG,就会默认走弱读。这个时候 obproxy_read_consistency=0、SET ob_read_consistency=3 都不管用。如果遇到"配了强读结果还是读到了备副本",就先检查这个开关。
# 弱读参数
ob_read_consistency=2 # 设置数字2,表示WEAK
ob_read_consistency=3 # 设置数字3,表示STRONG
2. 参数设成 1 之后,客户端的 SET 会被拒绝
obproxy_read_consistency=1 生效后,会话会被标记成 follower 用户,这时候再执行 SET ob_read_consistency,ODP 会直接报错拒掉(set ob_read_consitency is not allowed)。唯一的例外是 SQL hint 还能盖过去。
3. 优先用 SQL hint
需要"整体弱读、个别业务强读"的话,ODP 参数配 1,个别 SQL 加 /*+ READ_CONSISTENCY(STRONG) */;反过来也一样。再有一种建议,是单独部署一个"弱读专属"的 ODP。
4. 弱读生效条件
- 语句是 SELECT(非 SELECT 一律强读)
- 非
FOR UPDATE - 不在事务中(事务内默认强读,除非配了
enable_transaction_split) - 集群存在可用备副本/只读区
- server 版本支持弱读
5. observer 全局变量 ≠ ODP 弱读开关
想让 ODP 上的流量走弱读,应该配 ODP 参数或客户端 hint/SET;改 observer 全局 ob_read_consistency 只影响"到了 server 后怎么读",不会产生弱读路由。
五、弱读速查
单条弱读: SELECT /*+ READ_CONSISTENCY(WEAK) */ ...
连接弱读: SET ob_read_consistency = 2;
全局弱读: ODP: obproxy_read_consistency = 1 (OCP / ALTER PROXYCONFIG)
优先级: hint > 客户端 SET > ODP 参数 > observer 全局
生效条件: 非事务 SELECT + 有备副本 + 无 FOR UPDATE
头号大坑: enable_read_write_split 开启后默认弱读,强读只能靠 hint




