Проблема блокировки в 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)
Любые предложения приветствуются!
Ответы
Ответ 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
Я столкнулся с подобными проблемами, и это было решено следующими шагами.
Различные драйверы реализованы по-разному, некоторые драйверы все равно будут работать на соединение, если базовый результатSet не закрыт.
- Настройки 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 показывает, что все соединения не были закрыты на сервере/консоли сервера.