【 使用环境 】测试环境
【 OB or 其他组件 】obproxy
【 使用版本 】4.2.3.0-3
【问题描述】在读文档后知道一致性读级别是事务级别的,根据事务第一个语句来确认。如果第一个是弱一致性的,后面如果有dml或者for update等锁语句会报错。我的疑问是,能否实现如果java程序中开了事务就走强一致性,没有开事务就走弱一致性读呢,读不到才路由到主库。类似shardingshpere 的transactionalReadQueryStrategy参数设置为primary。设想,如果obproxy解析到有事务语句,就自动将此会话的一致性读设置为强读,事务完成后再改回去?不知道有这种方法或者配置参数没
【复现路径】问题出现前后相关操作
【附件及日志】推荐使用OceanBase敏捷诊断工具obdiag收集诊断信息,详情参见链接(右键跳转查看):
目前 OceanBase 并没有直接提供一个参数或配置项来自动切换事务内外的一致性级别。不过,您可以通过编程逻辑结合 OceanBase 的特性来实现类似的功能:
- 编程逻辑控制:
- 当 Java 应用程序开始一个事务时(比如调用了
START TRANSACTION
或者相应的 API),可以先设置会话的一致性级别为STRONG
。 - 当事务结束时(比如调用了
COMMIT
或ROLLBACK
),再将一致性级别设置回WEAK
。 - 对于未在事务中的查询,您可以直接设置其一致性级别为
WEAK
,或者通过 hint 来指定。
- 利用 hint 特性:
- 对于不在事务中的查询,可以使用 hint (
/*+READ_CONSISTENCY(WEAK)*/
) 来指定弱一致性读。 - 对于事务中的查询,不需要额外设置,因为事务内的第一条语句决定了整个事务的一致性级别。
- 备优先读策略:
- 您提到的读不到数据时路由到主库的需求,可以通过设置
proxy_route_policy
为'follower_first'
来实现。这会在弱一致性读的情况下优先路由到备节点,如果备节点读不到数据,OceanBase 会自动路由到主节点。
综上所述,虽然 OceanBase 目前并没有直接提供一个参数来自动切换事务内外的一致性级别,但您可以通过上述方法组合使用来达到类似的效果。这种方式需要在应用程序层面做一些额外的工作,但可以满足您的需求。
请注意,这种实现方式需要您在应用程序中对事务管理有一定的控制能力,并且需要确保应用程序正确地处理事务的开始和结束。此外,还需要确保应用程序能够正确地使用 hint 来指定一致性级别。
希望以上信息能对您有所帮助!如果您还有其他具体的技术问题,欢迎继续提问。
具体信息可参考以下文档:
领导们就是想不侵入代码,以现有代码来搞。
可以不修改业务代码,但是要调整一下基础设施封装。
比如定义两个数据源,再自己实现 org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource
接口,检测到 @Transactional
注解 或 满足其他自定义条件 就访问 主库 数据源,否则访问 从库 数据源。
从库 可以配置一个只读账号,然后在 JDBC URL 参数里面加上 &sessionVariables=ob_read_consistency=WEAK
即可,亲测可用。
BTW,虽然我们这样实现了,但后来我们又取消了读写分离。
主要考虑到 3 点:
- OB 有慢查询抑制机制,也有请求超时机制,能够一定程度上抑制 慢查询 的满载 对 正常查询 的负面影响。
- 查 从库,会有 数据一致性 的延迟问题,有可能读到脏数据(数据库CPU、磁盘IO 负载高时,还是比较可能出现),除非你的业务上能够容忍。
- 如果你有 30 个数据表,使用 OB 3副本集群,OB 大概率会将 每10表 主副本 放在 不同的 Zone。比如【表1~10】 的主副本在Zone 1,【表11~20】 的主副本在Zone 2,【表21~30】 的主副本在Zone 3。默认是 强一致性读,对应表的数据读写也都访问的是其 主副本 所在的 Zone。这样本身也是相对比较均衡的。它并不是像 MySQL 那样——所有数据表的 写入都是在一个主节点。
好的,明白了。感谢!!
另外,看您的表述,又生出一个问题,如果是这样分,多表连接时,A表主副本在zone1,B表主副本在zone2,他们如何关联查询呢?数据扫描出来在obproxy执行关联么?有相关文档地址没,指点下
请问在配置读写分离后,能确定当前这个被路由到哪一个节点去了么?比如mysql mgr的server_id不同,每次查询这个id就能确认到哪儿了。ob有类似方法没?我一个一个节点直连过,发现server_id好像都一样
用explain route?还有其他方法没
在强一致性下,如果主副本跨多个 Zone,OB 可能会生成 分布式执行计划 或 远程执行计划( 跨多个Zone,也并非一定就是分布式/远程的执行计划,OB 会根据实际情况判断 )。
如果是开启事务,涉及到多个 Zone 的,也可能会变成 分布式事务。
必要时,OB 也会 并行执行。
为了尽量让 OB 优先走 本地执行计划、本地事务,所以我们可以将需要关联查询/更新的多个业务表,添加到 同一个表组 里面。
这样,它们的 主副本 都会放在同一个 Zone,这样性能会稍微好一些。
感谢!又get到新知识了
obproxy日志可以看到sql的轨迹