Весенняя партия : HikariPool-1 — Подключение недоступно, время ожидания запроса истекло через 30000мс

#spring-batch

Вопрос:

У меня следующая ошибка с 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;
        }
 

Я использовал «Целое число.MAX_VALUE» для corePoolSize, maxPoolSize и емкости очереди (вместо 64), но ошибка все равно возникает.

Правка : В конце концов, причиной моей проблемы, по-видимому, является вызов хранимой процедуры в beforeJob. Действительно, когда я комментирую этот код ниже, он работает.

 @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();
 

Ответ №1:

Вы исчерпываете пул подключений к базе данных, потому что не закрываете соединения, чтобы вернуть их обратно в пул. Вы звоните только close по CallableStatement телефону . Попробуйте что-нибудь в этом роде…

 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 соединений.

Комментарии:

1. Большое вам спасибо, вы правы. Я решил свою проблему. Хорошего вам конца дня.

Ответ №2:

Здесь есть два ключевых параметра: размер пула рабочих потоков и размер пула соединений базы данных.

Если каждый поток запрашивает подключение к базе данных, и у вас больше работников, чем доступных подключений, то в какой-то момент рабочие потоки будут ждать, пока подключения станут доступными. Это ожидание может затянуться, если соединения не будут освобождены до заданного значения тайм-аута.

Поэтому вам нужно убедиться, что у вас достаточно соединений для рабочих потоков, или увеличить время ожидания в пуле соединений.