Spring Boot调用Azure SQL Server长时存储过程的优化方案咨询
问题:Azure SQL Server长耗时存储过程调用的SocketTimeout问题及优化需求
场景与问题详情
我需要在Azure SQL Server上运行一个耗时约20分钟的存储过程,最初采用Spring Data JPA的方式调用,代码如下:
public interface MyRepository extends JpaRepository<MyEntity, Integer> { @Procedure(procedureName = "my_procedure") void my_procedure(); } private void importProcedure(){ repository.my_procedure(); } @Transactional(propagation = Propagation.REQUIRES_NEW, timeout = 6) public void import_procedure_conferimenti() { log.info("Start"); CompletableFuture<Void> future = CompletableFuture.runAsync(this::importprocedure); future.thenAccept(result -> { log.info("Finish"); }).exceptionally(throwable -> { log.error("Error", throwable); return null; // Return a default value in case of an error }); }
对应的Spring数据源配置:
datasource: driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver url: jdbc:sqlserver://db:port;database=db-name;user=user;password=pwd;...;socketTimeout=60000 hikari: minimum-idle: 10 maximum-pool-size: 50
但这种方式因URL中的socketTimeout=60000参数触发了SocketTimeout错误,原因是等待响应的套接字超时导致。
当前临时解决方案
我通过直接操作JDBC连接的方式解决了该问题,代码如下:
public Object executeProcedure(String procedureCall, int networkTimeoutMillis, int queryTimeoutSeconds) { Connection connection = null; PreparedStatement preparedStatement = null; ResultSet resultSet = null; Object result = null; try { connection = DataSourceUtils.getConnection(dataSource); connection.setNetworkTimeout(null, networkTimeoutMillis); preparedStatement = connection.prepareStatement(procedureCall); preparedStatement.setQueryTimeout(queryTimeoutSeconds); boolean hasResultSet = preparedStatement.execute(); if (hasResultSet) { resultSet = preparedStatement.getResultSet(); if (resultSet.next()) { result = resultSet.getObject(1); // Return the result as an Object } } } catch (SQLException e) { log.error("Error during procedure execution: " + e.getMessage(), e); } finally { if (preparedStatement != null) { try { preparedStatement.close(); } catch (SQLException e) { log.error("Error: " + e.getMessage(), e); } } if (connection != null) { DataSourceUtils.releaseConnection(connection, dataSource); } } return result; }
该方法能正常运行,但我不确定这是否为最优方案,因为需要为每个过程指定自定义超时。
期望实现的目标
我希望能实现以下效果:
- 调用存储过程
- 关闭连接以避免SocketTimeout
- 在处理过程中接收响应
- 完成时获取结果(考虑采用轮询方式?)
相关环境:Spring Boot 2.3,Java 1.8。
内容的提问来源于stack exchange,提问作者faienz93
相关产品推荐
相关产品推荐

