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

Spring Boot 1.5.10+JPA调用MySQL存储过程后会话未关闭致资源耗尽

解决Spring Boot JPA调用存储过程后MySQL连接不释放的问题

看你的描述,核心问题就是调用标注@Procedure的存储过程后,JDBC连接没被正确回收,最后把连接池耗干了,抛出CannotCreateTransactionException。结合Spring Boot 1.5.10这个版本的特性,还有我之前碰到过的类似问题,给你几个排查方向和解决方案:

1. 先排查存储过程本身的问题

有些存储过程内部可能藏着坑——比如没关闭的游标、残留的临时表,或者内部事务没正确提交/回滚,这会导致MySQL端的会话一直占着不放。

  • 先手动在MySQL客户端跑一遍:CALL refresh_mv_slave_holdings_for_master_fund(100);,然后用SHOW PROCESSLIST;看看调用完之后会话会不会自动消失。
  • 如果手动调用也留着会话,那问题肯定在存储过程本身,得优化它的逻辑,确保所有资源都释放,事务正常结束。

2. 绕过Spring Data JPA的默认实现,手动调用存储过程

Spring Data JPA 1.5.x的@Procedure注解在某些场景下确实有连接泄漏的bug,框架默认的实现没正确释放JDBC连接。你可以试试用EntityManager手动实现调用,自己控制资源:

@Repository
public class ProductRepositoryImpl implements ProductCustomRepository {

    @PersistenceContext
    private EntityManager entityManager;

    @Transactional
    public void refreshSlaveProductHoldings(Integer productId) {
        StoredProcedureQuery query = entityManager.createStoredProcedureQuery("refresh_mv_slave_holdings_for_master_fund");
        query.registerStoredProcedureParameter(1, Integer.class, ParameterMode.IN);
        query.setParameter(1, productId);
        try {
            query.execute();
        } finally {
            // 手动清理,确保连接被回收
            if (!query.isClosed()) {
                query.close();
            }
        }
    }
}

这种方式能精准控制存储过程调用的生命周期,避开框架层面的坑。

3. 调整Tomcat连接池的参数,强制回收泄漏的连接

你已经设了spring.datasource.tomcat.max-active=300,可以再加几个参数让连接池更“主动”地回收泄漏的连接:

# 连接空闲超过60秒就强制回收
spring.datasource.tomcat.remove-abandoned-timeout=60
# 启用连接回收机制
spring.datasource.tomcat.remove-abandoned=true
# 记录回收日志,方便排查哪块出的问题
spring.datasource.tomcat.log-abandoned=true

这算是临时救急的办法,能缓解连接耗尽的问题,但还是得从根源解决。

4. 检查事务配置是否冲突

你说存储过程在@Transactional块里调用,得确认:

  • 事务的传播行为是不是合理,别搞出嵌套事务或者事务没正常提交/回滚的情况。
  • 如果存储过程内部自己开了事务,可能和Spring的事务管理冲突,导致连接被死死拿着。可以试试把@Transactional的传播属性改成NOT_SUPPORTED,让Spring不插手存储过程的事务:
@Transactional(propagation = Propagation.NOT_SUPPORTED)
public void refreshSlaveProductHoldings(Integer productId) {
    // 存储过程调用逻辑
}

5. 考虑升级Spring Boot版本(如果可行的话)

Spring Boot 1.5.x早就停止维护了,后续的2.x版本修复了一大堆JPA和连接池相关的bug。如果项目允许升级,直接升到稳定的2.x版本,大概率能从根上解决这个连接泄漏的问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 03:48:06