Spring 批处理:HikariPool-1 - 连接不可用,请求在 30000 毫秒后超时
Spring Batch : HikariPool-1 - Connection is not available, request timed out after 30000ms
我在 SpringBatch 中遇到以下错误:
org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.
鉴于我有很多文件要加载,我认为错误是因为我的 TaskExecutor :
@Bean
public TaskExecutor MyTE() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(64);
executor.setMaxPoolSize(64);
executor.setQueueCapacity(64);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setThreadNamePrefix("MyTE-");
return executor;
}
我对 CorePoolSize、MaxPoolSize 和 QueueCapacity 使用了“Integer.MAX_VALUE”(而不是 64),但仍然出现错误。
编辑:最终,我的问题似乎是对存储过程的调用
在之前的工作中。的确,当我在下面评论这段代码时,它起作用了。
@Override
public void beforeJob(JobExecution jobExecution) {
CallableStatement cs=null;
cs=MyDataSource.getConnection().prepareCall("CALL my_proc(?,?)");
cs.setString(1, "my_arg1");
cs.setString(2,"my_arg2");
cs.execute();
cs.close();
但是,我想做这个调用,但我不明白为什么它会产生问题。 cs.close();
的连接似乎已关闭
有什么问题?
此致。
解法:
Connection con = null;
CallableStatement cs = null;
con=MyDataSource.getConnection();
cs=con.prepareCall("CALL my_proc(?,?)");
cs.setString(1, "my_arg1");
cs.setString(2,"my_arg2");
cs.execute();
cs.close();
con.close();
这里有两个关键参数:工作线程池的大小和数据库连接池的大小。
如果每个线程都请求一个数据库连接,而您的工作线程数多于可用连接数,那么工作线程有时会等待连接可用。如果在配置的超时值之前没有释放任何连接,此等待可能会超时。
因此您需要确保您的工作线程有足够的连接,或者增加连接池的超时时间。
您正在耗尽数据库连接池,因为您没有关闭连接以将它们释放回池中。您只在 CallableStatement
上呼叫 close
。尝试这样的事情...
try (Connection conn = MyDataSource.getConnection()) {
CallableStatement cs= conn.prepareCall("CALL my_proc(?,?)");
cs.setString(1, "my_arg1");
cs.setString(2,"my_arg2");
cs.execute();
cs.close();
}
这将自动关闭 Connection
对象并将其释放回 DataSource
连接池。
我在 SpringBatch 中遇到以下错误:
org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is java.sql.SQLTransientConnectionException: HikariPool-1 - Connection is not available, request timed out after 30000ms.
鉴于我有很多文件要加载,我认为错误是因为我的 TaskExecutor :
@Bean
public TaskExecutor MyTE() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(64);
executor.setMaxPoolSize(64);
executor.setQueueCapacity(64);
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
executor.setThreadNamePrefix("MyTE-");
return executor;
}
我对 CorePoolSize、MaxPoolSize 和 QueueCapacity 使用了“Integer.MAX_VALUE”(而不是 64),但仍然出现错误。
编辑:最终,我的问题似乎是对存储过程的调用 在之前的工作中。的确,当我在下面评论这段代码时,它起作用了。
@Override
public void beforeJob(JobExecution jobExecution) {
CallableStatement cs=null;
cs=MyDataSource.getConnection().prepareCall("CALL my_proc(?,?)");
cs.setString(1, "my_arg1");
cs.setString(2,"my_arg2");
cs.execute();
cs.close();
但是,我想做这个调用,但我不明白为什么它会产生问题。 cs.close();
有什么问题?
此致。
解法:
Connection con = null;
CallableStatement cs = null;
con=MyDataSource.getConnection();
cs=con.prepareCall("CALL my_proc(?,?)");
cs.setString(1, "my_arg1");
cs.setString(2,"my_arg2");
cs.execute();
cs.close();
con.close();
这里有两个关键参数:工作线程池的大小和数据库连接池的大小。
如果每个线程都请求一个数据库连接,而您的工作线程数多于可用连接数,那么工作线程有时会等待连接可用。如果在配置的超时值之前没有释放任何连接,此等待可能会超时。
因此您需要确保您的工作线程有足够的连接,或者增加连接池的超时时间。
您正在耗尽数据库连接池,因为您没有关闭连接以将它们释放回池中。您只在 CallableStatement
上呼叫 close
。尝试这样的事情...
try (Connection conn = MyDataSource.getConnection()) {
CallableStatement cs= conn.prepareCall("CALL my_proc(?,?)");
cs.setString(1, "my_arg1");
cs.setString(2,"my_arg2");
cs.execute();
cs.close();
}
这将自动关闭 Connection
对象并将其释放回 DataSource
连接池。