Java JDBC超时需分三层配置:connection-timeout控制连接池取连接等待(如HikariCP设3秒),connectTimeout/socketTimeout防御网络异常(如5秒TCP握手、读取超时),setQueryTimeout()终止慢SQL执行(单位秒,如10秒)。

Java 中配置 JDBC 超时时间,核心是分清三类超时:连接建立、网络读取、SQL 执行。只设其中一种,无法防止线程无限阻塞;必须按层配置、各司其职。
connectionTimeout:拿不到连接就快速失败
这是连接池层面的超时,不是 JDBC 驱动本身的参数。它控制的是应用从连接池获取一个可用 Connection 的最大等待时间。
- HikariCP 中用 connection-timeout(单位毫秒),推荐设为 3000(3 秒)
- 超过该时间未拿到连接,直接抛
SQLException,不会卡住线程 - 它和 JDBC URL 里的
connectTimeout不同:connectTimeout是驱动尝试建立 TCP 连接的时限,而connection-timeout是在连接池里“排队等连接”的时限
connectTimeout 与 socketTimeout:防御网络异常
这两个是 JDBC URL 或 Properties 中传给驱动的底层网络参数,单位都是毫秒。
- connectTimeout:TCP 握手阶段超时,比如 DNS 解析慢、目标端口不通、防火墙拦截。设为 5000 较稳妥
-
socketTimeout(MySQL 叫
socketTimeout,Oracle 叫oracle.jdbc.ReadTimeout):控制 Socket 接收数据包的等待时间。但注意——它只在“等第一个字节”或“等下一个数据包”时计时;一旦 Oracle 开始返回元数据或 MySQL 返回首行,计时就停止,后续慢查询完全不受影响 - 它们对数据库内部执行慢(如大表全扫、PL/SQL 死循环)无效,不能替代 queryTimeout
setQueryTimeout():唯一能终止慢 SQL 的机制
这是真正防止 executeQuery() 或 executeUpdate() 卡死的关键。它由 JDBC 驱动在客户端启动独立定时器,超时后强制关闭 Socket 并抛出异常。
立即学习“Java免费学习笔记(深入)”;
- 必须在
execute之前调用,例如:stmt.setQueryTimeout(10)(单位是秒,不是毫秒) - 值为 0 表示不启用(默认行为);设 10 就是 10 秒后中断并抛
SQLState HYT00或 ORA-17127 - Spring JdbcTemplate 直接提供
setQueryTimeout(30)方法;MyBatis 在<select timeout="30">中声明即可 - Oracle 12c+ 的 ojdbc8.jar 对该机制做了响应优化,中断更及时;ojdbc6 可能延迟数秒才生效
别漏掉事务与连接生命周期的超时
光有 statement 超时还不够,需配套收紧其他环节:
- Spring 事务加
@Transactional(timeout = 5),防止 autocommit=false 下事务空悬 - HikariCP 开启
leakDetectionThreshold=60000(60 秒),自动检测未关闭的 Connection - 避免在 parallelStream 或虚拟线程中裸用同步 JDBC;必须用
CompletableFuture.supplyAsync(..., dbPool)拆离 DB 操作,并为dbPool单独配小线程池(如 core=4, max=8) - 每个数据库操作应独立获取、使用、关闭连接,不要跨 lambda 捕获 Connection 或 PreparedStatement


















