jdbc连接偶尔卡死是因为rac模式下ons未就绪或6200端口不通导致30秒超时,tnsping仅验证监听器可达性,不触发ons连接流程;典型表现为首次连接卡顿、日志报oracle.ons.noserversavailable,后续连接正常。

为什么tnsping通但JDBC连接偶尔卡死
tnsping只测监听器TCP层可达性,不走完整JDBC握手流程。真正卡在JDBC连接阶段的间歇性中断,大概率是ONS(Oracle Notification Service)未就绪或端口不通导致的30秒超时——这是RAC特有现象,和网络、监听器本身无关。
典型表现:应用启动首次连接JDBC时卡30秒,日志出现oracle.ons.NoServersAvailable: Subscription time out;后续连接正常。根本原因是JDBC驱动默认启用FAN(Fast Application Notification),会尝试连接节点上的6200端口拉取ONS事件,失败后才退回到基础连接模式。
- 确认RAC所有节点的
ons daemon是否运行:crsctl stat res ora.ons -w "STATE",状态必须为ONLINE - 检查客户端能否访问每个RAC节点的
6200端口:telnet node1 6200、telnet node2 6200,防火墙必须双向放行TCP 6200 - 临时禁用ONS(仅用于验证):在JDBC URL末尾加
&oracle.net.disableOcm=true,若卡顿消失,即锁定问题根源
SCAN解析成功但连接随机失败
SCAN域名能nslookup查到3个IP,不代表客户端每次都能拿到全部IP或选到可用节点。DNS负向缓存、本地resolver乱序返回、glibc DNS轮询策略都可能导致某次连接固定落到已宕机或未就绪的节点上,表现为“有时连得上,有时ORA-12541”。
不要依赖tnsping rac-scan结果——它只试第一个IP。真正要模拟JDBC行为,得用sqlplus /@rac-scan反复执行10次,观察失败是否集中在某个IP。
- 强制客户端跳过DNS,直接用
/etc/hosts写死全部SCAN IP和对应节点VIP,格式必须严格:192.168.10.100 rac-scan.example.com - 在
sqlnet.ora中设置NAMES.DIRECTORY_PATH=(HOSTNAME,TNSNAMES,EZCONNECT),确保HOSTNAME排第一 - 若用JDBC,URL里避免
@rac-scan.example.com,改用@//192.168.10.100:1521/ORCLPDB直连单点测试,排除SCAN负载分发干扰
JDBC连接池配置让“断连”变“僵尸”
连接池把已断开的物理连接当成活跃连接复用,是间歇性中断的放大器。比如HikariCP没开泄漏检测,应用层漏调connection.close(),连接池持续复用这个半死连接,直到某次SQL执行时才暴露异常(ORA-17008、ORA-01041),看起来像“突然中断”。
关键不是连接池本身,而是它掩盖了底层连接的真实状态。Oracle JDBC驱动不会主动探测连接是否存活,全靠连接池自己判断。
- 启用HikariCP的
leak-detection-threshold=60000(毫秒),捕获未关闭连接的堆栈 - 设
connection-timeout=3000(3秒),避免网络闪断后连接卡在“等待响应”状态过久 - 加
validation-timeout=2000和connection-test-query=SELECT 1 FROM DUAL,每次借出前做轻量验证 - Oracle JDBC URL里别加无效参数如
characterEncoding=utf8,旧驱动可能静默忽略,但影响健康检查逻辑
连接建立阶段报ORA-12170却说网络正常
ORA-12170本质是服务端监听器accept()慢,不是客户端connect timeout。常见于RAC中SCAN监听器未完全就绪,或sqlnet.ora里SQLNET.INBOUND_CONNECT_TIMEOUT设得太小(默认60秒),而监听器因DNS反向解析、ACL检查、Wallet协商等卡住。
注意:这个参数只控制“监听器接受连接”的耗时上限,不影响SQL执行超时。它必须在所有RAC节点的$ORACLE_HOME/network/admin/sqlnet.ora里统一配置,否则部分节点仍会超时。
- 在所有节点
sqlnet.ora中显式设SQLNET.INBOUND_CONNECT_TIMEOUT = 180 - 关掉监听器的反向DNS解析:
lsnrctl set log_status off后,在listener.ora加DISABLE_VALIDATION=ON - 检查
$GRID_HOME/log/<node>/agent/</node>下的oraagent_grid.log,搜索Failed to bind address或TNS-12545,这些才是真实瓶颈线索











