UCP必须显式启用FCF,即调用setFastConnectionFailoverEnabled(true),否则RAC节点宕机后应用仍向故障实例发请求,导致ORA-03113或连接重置;该设置不能依赖JDBC URL或connectionProperties中的fanEnabled配置,且须在PoolDataSource初始化后、首次获取连接前执行。

UCP必须显式启用FCF,setFastConnectionFailoverEnabled(true)不能省
看到RAC节点宕机后应用还在往坏实例发请求、报ORA-03113或IO Error: Connection reset,基本就是FCF没真正生效。UCP不会从JDBC URL里的oracle.jdbc.fanEnabled=true自动识别开关,也不会读取connectionProperties里的同名配置项。
必须在PoolDataSource初始化后、首次获取连接前,调用setFastConnectionFailoverEnabled(true)。Spring Boot里得用@PostConstruct或InitializingBean.afterPropertiesSet()触发,不能只写在配置类构造函数里。
- 服务端前提:RAC service已启用FAN(
srvctl config service显示FAILOVER_TYPE=SELECT),且ONS连通性验证通过(onsctl ping -h rac1-vip -p 6200返回OK) - tnsnames.ora中彻底删除
FAILOVER=ON、LOAD_BALANCE=ON、FAILOVER_MODE块——FCF和TNS层重试逻辑互斥,共存会导致连接卡死在已下线节点 - JDBC URL必须用SCAN地址或tnsnames别名,禁用Easy Connect格式(如
jdbc:oracle:thin:@//rac1-vip:1521/my_service)
setConnectionFactoryClassName不设就抛IllegalStateException
UCP初始化失败报connection factory class name is not set,不是URL或密码错了,是根本没告诉池该用哪个类来创建物理连接。这个参数是强制的,漏掉直接启动失败。
填"oracle.jdbc.pool.OracleDataSource"最稳妥;别写成"oracle.jdbc.driver.OracleDriver",那是Driver类,UCP会类型转换失败。
立即学习“Java免费学习笔记(深入)”;
- URL必须含
SERVICE_NAME(非SID),例如jdbc:oracle:thin:@//host:1521/ORCLPDB1 - 若用tnsnames.ora,需确保文件在
$ORACLE_HOME/network/admin且类路径包含该目录,再配合setConnectionPoolName("my_pool")和setURL("jdbc:oracle:thin:@MY_TNS") - 驱动未注册时(尤其容器环境),加一句
DriverManager.registerDriver(new oracle.jdbc.OracleDriver())防ClassLoader隔离问题
高并发下validateConnectionOnBorrow是性能瓶颈
压测时池“满”但活跃连接极少,线程大量阻塞在getConnection()上,大概率是同步验证拖垮了。默认开启的validateConnectionOnBorrow每次取连接都执行SELECT 1 FROM DUAL,网络延迟稍高就排队。
关掉它:pool.setValidateConnectionOnBorrow(false),改用异步校验组合:
-
pool.setConnectionValidationTimeout(5):单次验证超时5秒,避免长等 -
pool.setInactiveConnectionTimeout(60):空闲连接60秒未用即清理,防堆积 -
pool.setAbandonedConnectionTimeout(300):必须开!否则应用层漏close()会导致连接永久滞留
盲目调大maxPoolSize风险很高——Oracle每个会话占PGA内存,设到200+容易触发ORA-04030,建议先看v$session实际峰值再定。
连接亲和性靠connectionLabel,不是URL或池参数
想让同一用户会话的SQL尽量路由到同一个RAC实例(比如临时表、包变量依赖),别折腾URL加参数或改setConnectionPoolName——这些对亲和性完全无效。
亲和性本质是标签匹配:应用在getConnection(Properties)时传入Properties,其中key为自定义标签(如"user_id=123"),UCP内部按标签哈希选择物理连接。
- 必须实现
ConnectionLabelingCallback接口,重写cost()和configure()方法,否则标签只是摆设 - 标签值要稳定(比如用户ID),不能用时间戳、随机数这类每次变的值,否则失去“亲和”意义
- 不要和FCF混用同一套标签逻辑——FCF事件驱动失效感知,亲和性是路由策略,两者目标不同,配置要分开设计
最易忽略的是:亲和性不保证100%路由到同一实例,只提高概率;且一旦底层连接因FCF被清理,新建立的连接会重新匹配标签,状态无法跨连接延续。


















