必须使用oracle.jdbc.replay.OracleDataSourceImpl等专用类、启用AC服务、禁用连接池校验并确保事务边界完整,否则AC失效退化为普通TAF。

Java中配置Oracle Application Continuity(AC)不能靠Spring Boot自动装配或简单换驱动就能生效,必须显式使用 replay-aware 数据源、启用数据库端服务级配置,并规避 JDBC 连接池的默认行为——否则即使连上了 RAC,故障时仍会抛 SQLException 或静默丢事务。
必须用 oracle.jdbc.replay.OracleDataSourceImpl 替代普通 OracleDataSource
Spring Boot 的 spring.datasource.type 或 HikariCP 默认初始化的 OracleDataSource 不支持 replay。AC 要求所有连接必须来自 replay driver 提供的专用实现类:
-
oracle.jdbc.replay.OracleDataSourceImpl(推荐用于非XA场景) -
oracle.jdbc.replay.OracleConnectionPoolDataSourceImpl(配合 UCP 等连接池) -
oracle.jdbc.replay.driver.OracleXADataSourceImpl(XA 事务必需)
直接 new 实例并 setURL 是最稳妥方式,避免被 Spring Boot 的 auto-configuration 覆盖。URL 中必须包含 oracle.jdbc.replay=true 参数,例如:
jdbc:oracle:thin:@(DESCRIPTION=(ADDRESS_LIST=(ADDRESS=(PROTOCOL=TCP)(HOST=node1)(PORT=1521))(ADDRESS=(PROTOCOL=TCP)(HOST=node2)(PORT=1521)))(CONNECT_DATA=(SERVICE_NAME=orcl_ac)(FAILOVER_MODE=(TYPE=SELECT)(METHOD=BASIC)(RETRIES=3)(DELAY=5))))
注意:SERVICE_NAME 必须对应数据库中已启用 AC 的服务(通过 DBMS_SERVICE.CREATE_SERVICE(..., FAILOVER_METHOD => 'BASIC', FAILOVER_TYPE => 'SELECT', REPLAY_INITIATION_TIMEOUT => 30) 创建)。
立即学习“Java免费学习笔记(深入)”;
禁用连接池的预校验和连接复用干扰
HikariCP、UCP 等连接池默认的 connection-test-query 或 validationQuery 会破坏 AC 的上下文跟踪;连接复用(如 autoCommit=false 下复用连接执行多个事务)也会导致 replay 失败。
在 Java 中初始化和管理阿里云 SDK客户端。包括单例模式、线程安全、endpoint 与 region 配置、VPC 终端节点、同步与异步等。
- 关闭 HikariCP 的
connectionTestQuery,改用healthCheckSource配合自定义健康检查(只 ping 可用节点,不执行 SQL) - 设置
maximumPoolSize=1或严格按事务边界获取/关闭连接,避免跨事务复用同一物理连接 - 禁用 UCP 的
validateConnectionOnBorrow=false,AC 依赖驱动自身状态管理,外部校验会中断 replay 流程
典型错误现象:应用在 RAC 节点宕机后未重试,而是直接抛 java.sql.SQLRecoverableException: IO Error: Connection reset —— 这说明连接池提前“验证”失败,把 replay 机会扼杀在了源头。
事务方法必须声明为 @Transactional 且禁止手动 commit/rollback
AC 的 replay 机制仅对由 JDBC 驱动完整跟踪的事务生效。Spring 的 @Transactional 注解本身没问题,但以下行为会绕过 replay:
- 在 service 方法内调用
connection.commit()或connection.rollback() - 使用
JdbcTemplate执行 DDL(如CREATE TABLE),AC 不支持 DDL replay - 事务方法内嵌套调用另一个
@Transactional(propagation = Propagation.REQUIRES_NEW),新事务上下文无法继承 replay 上下文
驱动会在每个事务开始时注入 replay token,若事务中途被手动控制,token 就断了。此时即使数据库触发了 TAF 切换,JDBC 层也无法恢复语句流,只会报 ORA-25405: transaction is not active。
ojdbc8 驱动版本与 JVM、Oracle DB 版本强绑定
AC 在 ojdbc6 和 ojdbc7 中不可用;ojdbc8(com.oracle.database.jdbc:ojdbc8:21.10.0.0 或更新)是最低要求,且必须匹配 Oracle DB 12.2+:
- JDK 8u291+ 或 JDK 11+(ojdbc8 不兼容 JDK 7)
- Oracle DB 必须是 12.2.0.1 或更高(19c/21c/23c 均支持)
- 禁用
oracle.jdbc.useFetchSizeWithLongColumn=true(默认值),否则 LOB 操作 replay 时会报ORA-22922: nonexistent LOB value
最容易被忽略的是:AC 不是“开箱即用”的特性,它依赖数据库服务端开启、客户端驱动启用、应用层不破坏事务边界三者同时满足。少一个环节,就退化成普通 TAF 行为——只重连,不恢复请求。

















