Spring Boot集成测试时mssql-jdbc出现APPARENT DEADLOCK问题
解决Spring Boot + mssql-jdbc 6.1.0连接Azure SQL时的线程死锁问题
结合你遇到的APPARENT DEADLOCK错误,以及jstack显示线程卡在SocketInputStream.socketRead0的情况,大概率和老旧JDBC驱动、连接池配置不合理,或是Azure SQL的网络连接问题有关。我给你梳理几个针对性的解决步骤,按优先级尝试:
1. 优先升级mssql-jdbc驱动版本
你用的6.1.0.jre8是2017年的老版本,微软后续针对Azure SQL的适配、连接稳定性修复了大量bug,这个版本本身就存在不少socket阻塞和连接池兼容问题。直接升级到对应JDK8的最新稳定版(比如12.4.0.jre8),很多底层问题会直接消失。
如果是Maven项目,修改pom.xml的依赖:
<dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>mssql-jdbc</artifactId> <version>12.4.0.jre8</version> </dependency>
2. 调整C3P0连接池配置(从错误日志看你用的是C3P0)
错误里提到的ThreadPoolAsynchronousRunner是C3P0的组件,默认配置在集成测试的高并发场景下很容易出现连接耗尽或线程阻塞:
- 限制最大连接数:不要超过Azure SQL的连接上限(单数据库默认300),同时匹配你的测试并发量,比如设为50:
spring.datasource.c3p0.maxPoolSize=50 - 配置连接超时和自动回收:避免连接长期占用,添加这些配置:
spring.datasource.c3p0.minPoolSize=5 spring.datasource.c3p0.acquireIncrement=5 spring.datasource.c3p0.maxIdleTime=1800 spring.datasource.c3p0.checkoutTimeout=30000 spring.datasource.c3p0.idleConnectionTestPeriod=600 - 开启连接有效性检测:让C3P0定期检测空闲连接,避免拿到失效连接,比如
spring.datasource.c3p0.testConnectionOnCheckout=true(虽有轻微性能损耗,但能有效避免无效连接导致的阻塞)。
3. 检查Azure SQL的网络配置
线程卡在socket读取,可能是网络问题导致的:
- 确认测试环境的IP已经加入Azure SQL的防火墙允许列表,防止连接被中途切断。
- 完善JDBC URL的SSL配置,Azure SQL要求强制SSL,确保参数正确:
spring.datasource.url=jdbc:sqlserver://your-server.database.windows.net:1433;databaseName=your-db;encrypt=true;trustServerCertificate=false;hostNameInCertificate=*.database.windows.net;loginTimeout=30;
4. 排查测试代码的连接泄漏
确保测试代码里没有数据库连接泄漏:
- 所有的
Connection、Statement、ResultSet都要用try-with-resources语法自动关闭,或者在finally块中手动关闭:try (Connection conn = dataSource.getConnection(); PreparedStatement stmt = conn.prepareStatement("SELECT * FROM test_table")) { // 执行你的测试逻辑 } catch (SQLException e) { // 异常处理 } - 如果用了Spring的JdbcTemplate或者MyBatis,确保框架配置正确,它们本身会管理连接,但自定义连接获取逻辑的话一定要检查是否有泄漏。
5. 替换为HikariCP连接池(备选方案)
如果升级驱动和调整C3P0都没用,可以试试Spring Boot默认的HikariCP,它的性能和稳定性比C3P0更好,和mssql-jdbc的兼容性也更佳。只需要移除C3P0的依赖,添加Hikari的配置:
spring.datasource.hikari.maximum-pool-size=50 spring.datasource.hikari.connection-timeout=30000 spring.datasource.hikari.idle-timeout=600000 spring.datasource.hikari.max-lifetime=1800000
优先尝试升级驱动,这是解决这类问题最有效的办法。如果还有问题,可以再检查连接池和网络配置。
内容的提问来源于stack exchange,提问作者Gerb
相关产品推荐
相关产品推荐

