Oracle JDBC超时后看似卡死实为socketTimeout等待数据库返回下一批数据,需设socketTimeout(毫秒)并配setFetchSize(Integer.MIN_VALUE)流式读取,否则默认加载整结果集导致超时。
Oracle JDBC连接超时后直接断连,不是卡住
java读取大结果集时“卡死”,大概率不是网络真断了,而是jdbc驱动在等数据库返回下一批数据,期间socket层面已超时,底层抛出java.sql.sqltimeoutexception或java.net.sockettimeoutexception。这时候线程没挂,但resultset.next()会阻塞直到超时触发,再抛异常——看起来像卡住,其实是等超时。
关键点:超时控制分两层,一是建立连接阶段的connectTimeout,二是连接建立后传输数据时的socketTimeout(也叫oracle.net.CONNECT_TIMEOUT不生效,得用标准JDBC参数)。KeepAlive是TCP层保活,对Oracle长查询无实质帮助,别指望它防超时。
-
socketTimeout必须设,单位毫秒,建议从30000(30秒)起调,不能为0(禁用)也不能太大(掩盖慢SQL问题) - Oracle官方驱动(ojdbc8.jar)支持标准JDBC
socketTimeout,老版本ojdbc6可能需用oracle.net.READ_TIMEOUT替代 - KeepAlive由操作系统TCP栈控制,JDBC无法开启/关闭;JVM参数
-Dsun.net.client.defaultConnectTimeout和-Dsun.net.client.defaultReadTimeout对JDBC无效
配置socketTimeout的三种可靠写法
不是所有地方设了都生效。优先级:URL参数 > Properties对象 > setNetworkTimeout()(运行时动态设,但部分Oracle驱动版本不支持该方法)。
- URL里加:
jdbc:oracle:thin:@//host:port/service?socketTimeout=60000—— 最稳,驱动启动时即解析 - 用
Properties传参:Properties props = new Properties(); props.setProperty("socketTimeout", "60000"); DriverManager.getConnection(url, props); - 别用
connection.setNetworkTimeout():Oracle 12c+虽声明支持,但实测对大结果集流式读取(setFetchSize(Integer.MIN_VALUE))常不生效
大结果集必须配fetchSize,否则socketTimeout形同虚设
Oracle默认一次把整张结果集拉到内存,socketTimeout只管“单次网络读”的耗时,而默认fetchSize可能高达10000行。如果某一行特别宽(比如含CLOB),一次读就卡住几十秒,超时就触发了——这不是网络问题,是JDBC加载策略问题。
- 流式读取必须显式设
statement.setFetchSize(Integer.MIN_VALUE),让驱动用Oracle原生流协议(ROWID + 多次小包) - 若用
PreparedStatement,需在executeQuery()前设置,执行后再设无效 - 注意:
setFetchSize(1)看似更“流”,但会引发大量Round-Trip,反而更容易触碰socketTimeout,Integer.MIN_VALUE才是Oracle推荐值 - 搭配
resultSet.setFetchSize()无效,Oracle驱动只认Statement级设置
超时异常捕获后资源清理容易漏掉
超时抛出SQLTimeoutException时,ResultSet和Statement往往处于半关闭状态。不手动close,连接池(如HikariCP)可能回收失败连接,下次复用时报Closed Connection。
立即学习“Java免费学习笔记(深入)”;
- 必须在
catch (SQLTimeoutException e)块里显式调用resultSet.close()和statement.close(),哪怕外层有try-with-resources——因为超时可能发生在next()中间,资源未自动释放 - 别依赖
finally块里的close:如果超时发生在线程中断过程中,finally可能被跳过 - HikariCP的
leakDetectionThreshold能发现这类泄漏,但属于事后报警,不如代码里主动关干净
socketTimeout不是万能开关,它只解决“等太久”,不解决“为什么慢”。真正的大结果集瓶颈常在SQL执行计划、索引缺失或CLOB字段序列化上,参数调得再细,SQL本身不优化,照样超时。










