You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 03:05:18