mysql соединение Не могу прочитать ответ с сервера - PullRequest
0 голосов
/ 17 апреля 2020

MySQL 5.7, транзакция запущена, но поток спит, клиентский запрос (tomcat) блокируется, он будет длиться много секунд, после уничтожения соединения в MySQL, tomcat получает исключение:

org.springframework.dao.RecoverableDataAccessException: 
### Error querying database.  Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 852,932 milliseconds ago.  The last packet sent successfully to the server was 857,937 milliseconds ago.
at org.springframework.jdbc.support.SQLExceptionSubclassTranslator.doTranslate(SQLExceptionSubclassTranslator.java:98)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:73)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:82)
    at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73)
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)
    at com.sun.proxy.$Proxy59.selectList(Unknown Source)
    at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:230)
......

 at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
    at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:989)
    at com.mysql.jdbc.MysqlIO.nextRowFast(MysqlIO.java:2222)
    at com.mysql.jdbc.MysqlIO.nextRow(MysqlIO.java:1982)
    at com.mysql.jdbc.MysqlIO.readSingleRowSet(MysqlIO.java:3407)
    at com.mysql.jdbc.MysqlIO.getResultSet(MysqlIO.java:470)
    at com.mysql.jdbc.MysqlIO.readResultsForQueryOrUpdate(MysqlIO.java:3109)
    at com.mysql.jdbc.MysqlIO.readAllResults(MysqlIO.java:2334)
    at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2733)
    at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2549)
    at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1861)
    at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1192)
......

Caused by: java.io.EOFException: Can not read response from server. Expected to read 20,481 bytes, read 19,682 bytes before connection was unexpectedly lost.
    at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:3008)
    at com.mysql.jdbc.MysqlIO.nextRowFast(MysqlIO.java:2205)

Я использую alibaba druid Connection Pool, testOnBorrow = true, mysql java версия драйвера - 5.1.40

Вышеуказанное исключение выдается после разрыва соединения, tomcat блокирует, пока соединение убит.

Этот случай происходит несколько раз в производственном evn, его трудно повторить при разработке env.

Так как вызванное исключение Can not read response from server. Expected to read 20,481 bytes, read 19,682 bytes before connection was unexpectedly lost., клиент ожидает больше данных с сервера поэтому я предполагаю, что соединение, заимствованное из пула, сначала допустимо, но почему не удается прочитать больше данных с сервера?

Кстати: мы недавно использовали MySQL / * + MAX_EXECUTION_TIME (xxx) * / подсказку оптимизатора , MySQL выдаст Исключение, если запрос истек, я не знаю, связано ли это с моей проблемой, но я думаю, что не должно.

1 Ответ

0 голосов
/ 17 апреля 2020

Предположительно, ваш запрос от вашего сервлета выполнялся дольше, чем ваш MAX_EXECUTION_TIME. Во всяком случае, похоже, что ваш запрос истек, когда он выполнялся в течение 853 секунд.

И ваш сервлет потерпел крах. Предоставленная вами трассировка ошибок показывает, что произошло.

Если вы хотите, чтобы ваш сервлет восстановился после уничтожения соединений JDB C, вы должны запрограммировать его на перехват исключения, когда вы УБИВАЕТЕ его процесс базы данных, а затем повторите запрос.

Вам нужно будет поэкспериментировать, чтобы понять это правильно.

Вы можете форсировать сбой в разработке, используя гораздо более короткий MAX_EXECUTION_TIME. Либо вы можете получить доступ к своему серверу MySQL разработки с помощью командного клиента, найти processid процесса, обслуживающего ваш весенний сервлет, и KILL его вручную.

Причина root: я верю вашему запросу занимает слишком много времени Вы должны как-то оптимизировать это. Посмотрите на для идей об этом.

...