2009-04-11 4 views
1

Мы размещаем сервис (сервлет, выполняющийся на jboss), который получает что-то вроде 5-6 запросов в секунду. Каждому запросу необходимо подключиться к mysql через спящий режим. Большинство наших запросов выбирают, с вставкой/обновлением каждые 5/6-й запрос. Соединение hibernate mysql получает тайм-аут после тайм-аута соединения mysql (8 часов). Даже после того, как запрос на обслуживание нашего сервиса каждый час, соединение mysql иногда случайно отключается через день или около того. Мы хотим, чтобы спящий режим был повторно подключен, если соединение отключено по какой-либо причине и поддерживает количество подключений, к которым мы хотим.Соединение с гибернацией/mysql

Мы пытались C3P0, со следующей конфигурацией:

<property name=c3p0.acquire_increment>1</property> 
<property name=c3p0.idle_test_period>3600</property> 
<property name=c3p0.max_statements>0</property> 
<property name=c3p0.min_size>1</property> 
<property name=c3p0.timeout>3605</property> 
<property name=hibernate.c3p0.preferredTestQuery>select 1;</property> 

Hibernate размер connection_pool был установлен в 1.

Это сделало проблему тайм-аут/отключение уйти. Но мы столкнулись с другой проблемой. Долго ждет. Обычно время подачи запроса для нас составляет 2-3 мс для выбора и 40-50 мс для вставки/обновления. Но после использования вышеуказанной конфигурации C3P0 мы увидели, что каждый запрос, завершающийся после обновления, занимает больше минуты, а иногда и 4-5 минут! Из наших журналов казалось, что случайным образом запрос на выбор зацикливается и сможет завершить только после того, как будет получен и обслужит запрос на обновление.

Проблема выше, если мы удалим конфигурацию C3P0. Может кто-нибудь предположить, что мы можем делать неправильно?

Вот полный спящий режим конфигурации для справки:

<?xml version="1.0" encoding="utf-8" ?> 

<!DOCTYPE hibernate-configuration PUBLIC 
      "-//Hibernate/Hibernate Configuration DTD 3.0//EN" 
      "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"> 

<hibernate-configuration> 
    <session-factory> 

     <property name="connection.driver_class">com.mysql.jdbc.Driver</property> 
     <property name="connection.url">jdbc:mysql://xxx.xxx.xxx</property> 
     <property name="connection.username">xxx</property> 
     <property name="connection.password">xxx</property> 
     <property name="connection.pool_size">1</property> 
     <property name="dialect">org.hibernate.dialect.MySQLDialect</property> 
     <property name="current_session_context_class">thread</property> 
     <property name="hibernate.cache.use_query_cache">false</property> 
     <property name="hibernate.cache.use_second_level_cache">false</property> 
     <property name="show_sql">true</property> 

     <!-- Transaction isolation 2 = READ_COMMITTED --> 
     <property name="connection.isolation">2</property> 
     <property name="connection.autocommit">true</property> 

     <!-- configuration pool via c3p0--> 
     <property name="c3p0.acquire_increment">1</property> 
     <property name="c3p0.idle_test_period">3600</property> <!-- seconds --> 
     <property name="c3p0.max_size">1</property> 
     <property name="c3p0.max_statements">0</property> 
     <property name="c3p0.min_size">1</property> 
     <property name="c3p0.timeout">3605</property> <!-- seconds --> 
     <property name="hibernate.c3p0.preferredTestQuery">select 1;</property> 

    </session-factory> 
</hibernate-configuration> 

ответ

1

Я бы рекомендовал отказаться от C3P0 и с помощью службы имен JNDI и подключение к объединению, что JBOSS обеспечивает.

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

Некоторые больше ссылок могут быть уместны: http://www.hibernate.org/117.html и http://www.informit.com/articles/article.aspx?p=353736&seqNum=4 относительно Hibernate и закрытие соединений, и эта ошибку MySQL, который цитирует проблемы с MySQL, Hibernate и соединение: http://bugs.mysql.com/bug.php?id=10917

+0

hmmm, в настоящее время мы полностью удаляем управление соединением в спящем режиме, то есть мы запрашиваем только hibernate для текущего соединения (getCurrentConnection()), а затем выполняем запрос на нем. Мы никогда не открываем и не закрываем соединение явно в нашем коде. Возможно, нам нужно пересмотреть эту стратегию. – ashweta

+0

Но тогда мы также требуем высокой производительности (<50 мс). Мы не можем позволить себе открывать и закрывать соединение db каждый раз, когда приходит запрос. Итак, infact нам нужно объединить открытые соединения, которые поддерживаются hibernate/JNDI, которые мы можем использовать, не закрывая их сами. – ashweta

+0

@ashweta: Вам нужно прочитать это - http://www.hibernate.org/117.html. Поиск «Hibernate - это утечка JDBC-соединений!» Должен закрыть сеанс. Что касается производительности, то у вас есть пулы. «Закрыть» в этом случае действительно означает «возврат в пул». – duffymo

1

Что-то кажется неладно с вашей конфигурацией. Все параметры конфигурации должны находиться в пространстве имен hibernate.c3p0, а не c3p0. *.

Но это, вероятно, не проблема. Я думаю, что, скорее всего, ваш пул - это только одно соединение, и вы где-то сталкиваетесь с проблемами конкуренции. Скорее всего, вы не отпустите соединение, где вам нужно, или тупик по некоторым данным. Попробуйте установить maxPoolsize на что-то более высокое, например, 2 и посмотреть, смягчена ли проблема. Это, вероятно, означает, что вы неправильно возвращаете соединения.

0

документация JBoss Hibernate конкретно говорится в не использовать менеджер соединения пула Hibernate для непроизводственных систем (точно так же, как Hypersonic - я действительно не знаю, почему они потрудились грузить известные компоненты багги). Как ранее отмечалось, используйте стандартную настройку JBoss <datasource> и связанный с ней пул-менеджер (и настройте по мере необходимости).

Если есть недоразумение, то методы open() и close() переопределены диспетчером соединений. Даже объект Connection не является прямым подключением к базе данных, а является дескриптором диспетчера пула.

Реализация на получение нового соединения (он же открыто), чтобы запросить соединение из пула (который для повышения эффективности уже открыт, и, если настроить с помощью <prepared-statement-cache-size> свойства в datasource определении, также предыдущие PreparedStatement s еще связан к этому Connection). Этот вызов эффективен.

Когда close() вызывается в соединении (опять же, реализован диспетчером пула), состояние ссылки на соединение просто изменяется на «доступно» по сравнению с закрытием фактического подключения к базе данных. Это также эффективно. Поэтому рекомендуется максимально возможный объем вызовов open/exec/close, чтобы максимально использовать многопоточное использование доступных подключений в пуле.

Смежные вопросы