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

Воспроизведение com.mysql.jdbc.exceptions.jdbc4.CommunicationsException с настройкой Spring, спящего режима и C3P0

Я получил эту ошибку из производственного кода:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Последний пакет успешно принят с сервера was36940 секунд назад. Последний пакет успешно отправлен на сервер было 36940 секунд назад, который больше, чем сервер настроенное значение "wait_timeout". Вы должны рассмотреть либо истечение срока действия и/или проверка достоверности подключения перед использованием в вашей заявке, увеличение настроенного сервера значения для тайм-аутов клиента или использования свойство соединения Connector/J 'autoReconnect = true', чтобы избежать этого проблема.

И теперь я пытаюсь воспроизвести проблему локально и исправить ее. Я настраиваю контекст spring следующим образом:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
    destroy-method="close" p:driverClass="com.mysql.jdbc.Driver"
    p:jdbcUrl="jdbc:mysql://localhost:3306/test?userUnicode=yes&amp;characterEncoding=UTF-8&amp"
    p:idleConnectionTestPeriod="120" p:initialPoolSize="1" p:maxIdleTime="1800"
    p:maxPoolSize="1" p:minPoolSize="1" p:checkoutTimeout="1000"

/>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="hibernateProperties">
        <value>
            hibernate.connection.provider_class = org.hibernate.connection.C3P0ConnectionProvider
            hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
            hibernate.default_schema=platform_server_original
            hibernate.show_sql=false
        </value>
    </property>
    <property name="mappingResources">
        <list>
            <value>sometables.hbm.xml</value>
        </list>
    </property>
</bean>

Затем я устанавливаю mysql wait_timeout на 10 секунд, затем запускаю свой тест, который в основном открывает соединение, выполняет запрос, закрывает его, поэтому он возвращается в пул, затем сглаживает поток в течение 15 секунд, а затем открывает соединение снова, и повторите запрос, чтобы он сломался. Однако, я получил только ту же ошибку:

com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Ошибка связи канала связи

Последний пакет, отправленный на сервер, был 16 ms назад.

Итак, я удивляюсь, эти две ошибки одинаковы или они разные? Я сделал несколько исследований, и, похоже, обе ошибки сводились к одному и тому же решению: с использованием свойства "testConnectionOnCheckout = true". Однако, согласно документу c3p0, это очень дорогая проверка. Он советует использовать "idleConnectionTestPeriod", но я уже устанавливаю его на 120 секунд. Какое значение я должен использовать, чтобы он мог корректно проверить соединение в режиме ожидания?

Поэтому я в основном задаю две вещи: 1. Как воспроизвести ошибку, которую я получил в производственном коде? 2. Как его исправить?

Спасибо!

4b9b3361

Ответ 1

У меня были аналогичные проблемы с MySQL и пулом соединений. Проблема заключается в том, что вы сообщаете пулу подключений, что тайм-аут простоя составляет 30 минут, но база данных отключает соединение через 10 секунд. Поскольку ваш период проверки соединения на холостом ходу составляет 120 секунд, он оставляет немного меньше 110 секунд, чтобы пул использовал сломанное соединение!

Я бы использовал следующие настройки для производства:

MySQL:
wait_timeout=75
C3P0:
maxIdleTime=60
idleConnectionTestPeriod=55

Ответ 2

Fei - может быть одной из нескольких вещей, на самом деле не может говорить на основе информации, размещенной до сих пор.

Предложите добавить к вашему вопросу номера MySQL/ Spring/Hibernate/C3PO/JDBC, если есть известная проблема.

Сообщение об ошибке производства является общим, с множеством возможных причин. Некоторые ведут к вам:

  • Ошибка производства может указывать что ваше приложение не освобождение подключения к пул, когда это делается, предотвращая c3p0 от проверки. (C3p0 простаивающие проверки могут применяться только к uncheck-out.)

  • Убедитесь, что c3p0 действительно работает (вы можете использовать 'vanilla' соединения, если нет). В вашем тесте, если вы установили (например,) MySql wait_timeout = 10, поток приложений sleep = 35 и idleConnectionTestPeriod = 30, если пул работает, исключение должен уйти.

  • За счет простоя проверки: не используйте по умолчанию getTables() - возможно, установлен preferTestQuery для чего-то дешевого (-er) 'SELECT 1', возможно, для MySQL?

Ответ 3

Чтобы воспроизвести вашу ошибку, установите время ожидания соединения в своих свойствах MySQL на очень низкое значение, то есть 2 мс, и запустите запрос, который, как известно, имеет длительное время обработки. Вы можете установить свойство тайм-аута либо в строке подключения MySQL, либо через свойство, если вы используете файлы свойств для настройки вашего соединения JDBC. Вы можете найти Javadocs в своем конкретном подключении jaxax.sql.DataSource и в документах MySQL для определения того, как это сделать.