MSSQL休眠连接阻塞查询问题求助(附HikariCP配置及环境)
生产环境MSSQL休眠连接问题排查与解决方案
问题背景
多租户架构,需连接6个数据库,部署在30个Tomcat实例上,技术栈:Azul JDK 11.0.12.0.101、Apache Tomcat/9.0.54、MSSQL驱动12.8.0.jre11、HikariCP 5.1.0。多次调整HikariCP配置后仍存在休眠连接,通过sp_whoisactive工具发现会话休眠时长可达数小时,推测HikariCP未正确关闭连接;应用与数据库间存在Azure网关,且排查到HikariCP的PoolBase.quietlyCloseConnection方法硬编码15秒网络超时,怀疑该设置导致连接关闭失败。
针对性解决方案
1. 修复HikariCP连接关闭超时限制
HikariCP的PoolBase.quietlyCloseConnection方法硬编码了15秒网络超时,当Azure网关存在延迟时,该时间不足以完成连接关闭,导致MSSQL端会话残留为休眠状态。解决方式:
- 自定义
PoolBase子类,重写quietlyCloseConnection方法,将网络超时调整为与dataSource.socketTimeout一致的1500000毫秒:public class CustomPoolBase extends PoolBase { public CustomPoolBase(HikariConfig config, PoolEntryCreator poolEntryCreator) { super(config, poolEntryCreator); } @Override protected void quietlyCloseConnection(Connection connection, String closureReason) { if (connection != null) { try (Connection con = connection) { if (isUseJdbc4Validation()) { try { con.setNetworkTimeout(getExecutor(), 1500000); } catch (SQLException e) { // 忽略超时设置异常 } } LOGGER.info("Closing connection {}: {}", connection, closureReason); } catch (SQLException e) { LOGGER.debug("{} - Connection close failed", poolName, e); } } } } - 自定义
HikariPool子类,使用上述CustomPoolBase:public class CustomHikariPool extends HikariPool { public CustomHikariPool(HikariConfig config) throws SQLException { super(config, new CustomPoolBase(config, (poolBase, timeout) -> poolBase.createPoolEntry(timeout))); } } - 配置HikariDataSource使用自定义池:
HikariConfig config = new HikariConfig(); // 加载原有配置项 HikariDataSource dataSource = new HikariDataSource(config) { @Override protected HikariPool createPool(HikariConfig config) throws SQLException { return new CustomHikariPool(config); } };
2. 优化HikariCP连接回收与保活配置
结合Azure网关特性调整参数:
- 将
idleTimeout调整为Azure网关空闲超时(默认4分钟)的90%,即216000(3分36秒),避免网关提前断开连接。 - 保留
keepaliveTime=30000(30秒),确保连接定期向网关发送保活包,防止网关判定连接空闲断开。 - 维持
maxLifetime=1320000(22分钟),确保其小于MSSQL服务器默认30分钟的连接超时。
3. 修正连接有效性检测配置
替换低效的自定义检测语句,启用JDBC4原生验证:
- 移除
connectionTestQuery配置,HikariCP默认启用useJdbc4Validation=true,会调用MSSQL驱动的isValid()方法检测连接有效性,比自定义SQL更高效准确。 - 若需保留自定义检测,改为
SELECT 1,避免回滚事务的额外开销。
4. 排查并修复连接泄漏
利用leakDetectionThreshold=60000的日志输出定位问题:
- 检查Tomcat日志中是否存在
Connection leak detected警告,根据堆栈信息找到未正确关闭连接的代码。 - 强制使用
try-with-resources语法管理连接,确保连接自动归还到池:try (Connection conn = dataSource.getConnection()) { // 执行数据库操作 } catch (SQLException e) { // 异常处理逻辑 }
5. 调整Azure网关配置
- 登录Azure门户,将应用网关的空闲超时设置为大于HikariCP的
idleTimeout(建议设为5分钟)。 - 启用Azure网关的TCP keep-alive功能,防止长时间空闲的连接被网关强制断开。
6. MSSQL端临时应急措施
若休眠会话已阻塞业务,可临时执行脚本清理休眠超过1小时的会话:
DECLARE @kill varchar(8000) = ''; SELECT @kill = @kill + 'KILL ' + CONVERT(varchar(5), spid) + ';' FROM master..sysprocesses WHERE spid > 50 AND status = 'sleeping' AND DATEDIFF(minute, last_batch, GETDATE()) > 60; EXEC(@kill);
内容的提问来源于stack exchange,提问作者Ravirajsinh Vaghela
相关产品推荐
相关产品推荐

