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

com.microsoft.sqlserver.jdbc.sqlserverexception:流已关闭问题原因排查咨询

问题分析:com.microsoft.sqlserver.jdbc.SQLServerException: The stream is closed

环境信息

  • SQL Server版本:Microsoft SQL Server 2012 - 11.0.5548.0 (X64) Sep 6 2014 17:19:28 Copyright (c) Microsoft Corporation Enterprise Edition (64-bit) on Windows NT 6.3 <X64> (Build 9600: ) (Hypervisor)
  • Hibernate版本:hibernate-core-5.6.11.Final
  • JRE版本:jre1.8.0_281
  • Apache Tomcat版本:9.0.71
  • Spring Boot版本:2.7.4
  • JDBC驱动:mssql-jdbc-12.2.0.jre8.jar
  • 连接池:HikariCP-4.0.3.jar

Spring数据源配置

spring.datasource.url=jdbc:sqlserver://mydatabaseServer:51803;databaseName=mydatabaseName;encrypt=false;trustServerCertificate=true;socketTimeout=60000
spring.datasource.driver-class-name=com.microsoft.sqlserver.jdbc.SQLServerDriver
spring.datasource.password = mypassword
spring.datasource.testWhileIdle = true
spring.datasource.test-on-borrow=true
spring.datasource.validationQuery = SELECT 1
spring.datasource.sql-script-encoding=UTF-8
spring.datasource.username = myusername
spring.datasource.hikari.pool-name=myPool
spring.datasource.hikari.maximum-pool-size=300
spring.datasource.hikari.connectionTimeout=80000 
spring.datasource.hikari.max-lifetime=300000
spring.datasource.hikari.idle-timeout=60000
spring.datasource.hikari.leakDetectionThreshold=300000
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.SQLServer2012Dialect
spring.jpa.properties.hibernate.enable_lazy_load_no_trans=true
spring.jpa.open-in-view=false
spring.jpa.hibernate.naming-strategy = org.hibernate.cfg.ImprovedNamingStrategy

问题查询代码

@Repository
@Transactional(readOnly = true)
@Log4j2
public class SearchService {

    @PersistenceContext
    private EntityManager entityManager;
    
    public List<Request> searchRequests(SearchModel searchModel, int pageNumber) {
    

        CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
        CriteriaQuery<Request> criteriaQuery = criteriaBuilder.createQuery(Request.class);
        Root<Request> requestRoot = criteriaQuery.from(Request.class);
        requestRoot.alias("r");
        
        Predicate predicate = createConditions(requestRoot, criteriaBuilder, searchModel);
        criteriaQuery.select(requestRoot);
        Order orderBy = criteriaBuilder.desc(requestRoot.get("id"));
        String orderByProperty = searchModel.getOrderBy();
        criteriaQuery.where(predicate).orderBy(orderBy);

        // pageSize is 10
        // searchModel.getMaxResult() = 10
        // for pageNumber 1 startFrom will be 0 and maxResult will be 10
        int startFrom = (pageNumber - 1) * searchModel.getPageSize();
        List<Request> result = entityManager.createQuery(criteriaQuery).setMaxResults(searchModel.getMaxResult())
                .setFirstResult(startFrom).getResultList();
        return result;
    }

}

异常情况描述

该配置长期运行正常,但近期频繁抛出com.microsoft.sqlserver.jdbc.SQLServerException: The stream is closed异常,异常触发点为查询结果获取代码:

entityManager.createQuery(criteriaQuery).setMaxResults(searchModel.getMaxResult())
                    .setFirstResult(startFrom).getResultList();

对应的SQL语句为:

SELECT * FROM request ORDER BY id OFFSET 0 ROWS FETCH NEXT 10 ROWS ONLY;

直接在SQL Server执行该查询仅需10ms,但监控显示异常多次发生在该查询中。注意:Request实体/表无Eager关联和二进制列,但包含两个varchar(MAX)列,最大长度为5368。

可能的原因分析

应用端原因

  1. 连接池配置不匹配:HikariCP的max-lifetime设置为300秒,若SQL Server端的连接超时(如remote query timeout或连接生命周期)小于该值,会导致数据库主动关闭连接,但连接池仍认为该连接可用,当应用复用该连接时就会触发流关闭异常。另外testWhileIdle和test-on-borrow同时开启,可能存在校验逻辑冲突。
  2. JDBC驱动兼容性问题:mssql-jdbc-12.2.0是较新版本,对SQL Server 2012这种旧版本数据库可能存在兼容性bug,尤其是在处理varchar(MAX)列的结果流时,可能出现流被意外关闭的情况。
  3. Hibernate结果集处理问题:虽然查询本身执行快,但Hibernate在映射varchar(MAX)列到实体时,可能因连接提前释放导致流中断。比如@Transactional(readOnly=true)的事务边界是否覆盖了结果集读取的全流程,或者EntityManager的生命周期管理存在异常。
  4. 连接泄漏风险:虽然配置了leakDetectionThreshold=300000,但如果存在请求处理时间超过5分钟的情况,连接池会标记连接泄漏并回收,此时若应用仍在使用该连接读取结果,就会触发异常。

数据库/服务器端原因

  1. SQL Server连接超时设置变更:近期可能修改了数据库的remote query timeout、connection timeout等参数,导致数据库主动关闭长时间闲置或处理中的连接。
  2. 网络不稳定:应用服务器与数据库服务器之间的网络出现丢包、延迟波动或临时中断,即使查询执行完成,结果传输过程中连接断开也会触发流关闭异常。
  3. SQL Server资源瓶颈:数据库服务器内存不足、CPU使用率过高,导致查询结果的缓存或传输出现异常,强制关闭连接;或者数据库线程池耗尽,无法处理新的请求导致连接中断。
  4. Windows服务器TCP配置问题:Windows服务器的TCP连接超时、端口耗尽等系统级配置问题,导致操作系统主动关闭数据库连接。

排查建议

  • 查看SQL Server错误日志,确认是否有连接关闭相关的异常记录。
  • 调整HikariCP的max-lifetime,设置为比数据库端连接超时小30秒左右(例如若数据库连接超时为360秒,将max-lifetime设为330秒),避免数据库主动关闭连接池中的可用连接。
  • 尝试降级JDBC驱动版本至对SQL Server 2012支持更稳定的版本(如mssql-jdbc-9.4.1.jre8),验证是否为驱动兼容性问题。
  • 监控应用与数据库之间的网络状态,检查是否存在丢包、延迟异常等情况。
  • 开启JDBC驱动的debug日志,查看流关闭的具体时机和触发条件,定位问题根源。

内容的提问来源于stack exchange,提问作者Mahmoud Saleh

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 16:05:44