Подтвердить что ты не робот

Проблема блокировки в DBCP, развернутая на Tomcat

Я использую источник данных DBCP (с конфигурацией по умолчанию) в конфигурации Spring для управления моими подключениями к базе данных, и я запускаю условие взаимоблокировки, когда число клиентов увеличивается.

Я обнаружил, что в DBCP 1.2.1 есть проблема тупика, которую я использовал, которая должна была быть разрешена в 1.4. Поэтому я обновил до 1.4, но проблема все еще сохраняется.

В дампе потока есть много потоков, заблокированных следующей трассировкой стека:

   java.lang.Thread.State: WAITING on [email protected]
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:485)
at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1104)
at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106)
at org.apache.commons.dbcp.BasicDataSource.getConnection(BasicDataSource.java:1044)
at org.springframework.jdbc.datasource.DataSourceTransactionManager.doBegin(DataSourceTransactionManager.java:200)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:350)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:261)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:101)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:160)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:631)

Любые предложения приветствуются!

4b9b3361

Ответ 1

Я перешел на c3p0, несколько лет назад. Вы можете попробовать это. Я считаю, что вам не нужно много менять, это просто игра конфигурации.

Немного связанная нить, Параметры пула соединений с JDBC: DBCP vs C3P0. Ну, на самом деле я сделал это связанным.

[отредактировано, 19/10/12]

Tomcat 7 имеет приличный пул соединений, Пул соединений Tomcat JDBC.

Ответ 2

Вы убедились, что версия commons-pool соответствует версии dbcp?

Кроме того, я не вижу тупика в стеке, это просто похоже, что у вас есть потоки, ожидающие подключения для освобождения. Сколько потоков вы пытаетесь подключить одновременно? Сколько соединений вы настроили для пула и т.д.?

При отладке подобных случаев полезно также посмотреть, что делают потоки, которые получили соединение.

Ответ 3

Инкрустирующая нагрузка на приложение увеличивает потребность в одновременных подключениях. Поскольку ваши потоки висят на borrowConnection() - означает, что вы не имеете достаточного количества ActiveConnections.

Incrkease maxActive в свойствах datasource и установите WHEN_EXHAUSTED_BLOCK на некоторое время, например 600ms - 1000ms. Вы получите исключение No element available только по истечении 600 мс -1000 мс.

Ответ 4

Я думаю, что это вызвано не закрытием соединений в вашем коде приложения, поэтому у вас просто закончились соединения в пуле. Возможно, вы должны попытаться установить свойство "removeAbandoned" в DBCP. Это описано в http://commons.apache.org/dbcp/configuration.html как

Установка этого значения в true может восстановить соединения db из плохо написанных приложений которые не могут закрыть соединение.

Удачи!

Ответ 5

Я столкнулся с подобными проблемами, и это было решено следующими шагами.

  • Закройте все ресурсы базы данных в правильной последовательности

    resultSet.close();
    statement.close();
    connection.close();
    

Различные драйверы реализованы по-разному, некоторые драйверы все равно будут работать на соединение, если базовый результатSet не закрыт.

  1. Настройки Apache DBCP необходимо настроить

dataSource.setDefaultAutoCommit(true);
dataSource.setMaxActive(700); // make sure db server has it 800 dataSource.setRemoveAbandoned(true); dataSource.setTestOnBorrow(true); dataSource.setLogAbandoned(true); dataSource.setTestWhileIdle(true); dataSource.setTestOnReturn(true); dataSource.setRemoveAbandonedTimeout(60);

Убедитесь, что сервер базы данных может допускать как минимум 50+ соединений больше числа, указанного в setMaxActive, поскольку dbcp сначала дает x новые подключения, а затем пытается очистить соединения, превышающие число setMaxActive. При очистке dbcp показывает, что все соединения не были закрыты на сервере/консоли сервера.