Как избежать устаревших соединений MySQL / Hibernate (MySQLNonTransientConnectionException) - PullRequest
3 голосов
/ 06 апреля 2009

У меня есть веб-приложение на Java, использующее Hibernate и MySQL. Если сайт не используется в течение нескольких дней, соединение MySQL устареет, и меня встречает следующее исключение:

com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state.

Из опыта использования необработанного JDBC можно настроить соединение для попытки восстановления после ошибок или устаревших соединений, но я не знаю, как это сделать с помощью Hibernate. Я нигде явно не вызываю close () (но держу пари, что Hibernate делает что-то глубоко внутри).

Кто-нибудь знает, что мне делать?

Ответы [ 5 ]

4 голосов
/ 06 апреля 2009

Какой пул соединений вы используете?

Предложение Hibernate состоит не в том, чтобы использовать встроенный пул, а в использовании источника данных сервера приложений или чего-то вроде Commons DBCP или C3PO .

3 голосов
/ 06 апреля 2009

У меня была эта проблема. Использование пула соединений (c3p0) заставило его уйти. В общем, также неплохо использовать пул соединений.

2 голосов
/ 06 апреля 2009

Спасибо за совет. Ради потомков я изменил hibernate.cfg.xml из следующего:

<property name="connection.url">jdbc:mysql://localhost/FooDB</property>
<property name="connection.username">root</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.password">secret</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>

... на следующее:

<property name="connection.datasource">java:/comp/env/jdbc/FooDB</property> 
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>

Для этого также необходимо добавить стандартную запись context в context.xml моего веб-приложения:

<Resource name="jdbc/FooDB"
          auth="Container"
          type="javax.sql.DataSource"
          maxActive="100"
          maxIdle="30"
          maxWait="10000"
          username="root"
          password="secret"
          driverClassName="com.mysql.jdbc.Driver"
          url="jdbc:mysql://localhost:3306/ss?autoReconnect=true" />

1 голос
/ 06 ноября 2009
<property name="c3p0.acquire_increment">1</property> 
<property name="c3p0.idle_test_period">120</property> <!-- seconds --> 
<property name="c3p0.max_size">100</property> 
<property name="c3p0.max_statements">0</property> 
<property name="c3p0.min_size">10</property> 
<property name="c3p0.timeout">180</property> <!-- seconds --> 

переопределить эти настройки в вашем конфигурационном файле. Это поможет вам.

1 голос
/ 11 апреля 2009

У нас была похожая проблема истечения времени ожидания подключения к 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.

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

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

Вот полный конфиг hibernate для справки:

<?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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...