Spring 3 DataSourceTransactionManager sporadically timing out when getting transaction to MySQL - java

In a nutshell, when I try and get a connection after not having used a transaction for several minutes the first transaction setup fails.
When things are working, my logs show the following for a simple transaction:
DEBUG: org.springframework.transaction.annotation.AnnotationTransactionAttributeSource - Adding transactional method 'getRecord' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,timeout_30; ''
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [com.example.services.Service.getRecord]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,timeout_30; ''
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [jdbc:mysql://dev-db.example.com:3306/example, UserName=foo#1.2.3.4, MySQL Connector Java] for JDBC transaction
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [jdbc:mysql://dev-db.example.com:3306/example, UserName=foo#1.2.3.4, MySQL Connector Java] to manual commit
However, if I haven't had any activity for several minutes, instead I will get this message:
DEBUG: org.springframework.transaction.annotation.AnnotationTransactionAttributeSource - Adding transactional method 'getRecord' with attribute: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,timeout_30; ''
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Creating new transaction with name [com.example.services.Service.getRecord]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT,timeout_30; ''
My observations so far:
seems to be based on inactivity, but I've seen this behavior immediately after restarting my Tomcat although nothing else was hitting the database so I think it's inactivity against a network element such as my MySQL server.
when my application starts up, it makes a few non-transactional requests from the database which have not had any problems, so it seems related to transactions.
the timeout element in the #Transactional notation is not effective in this case. It seems to eventually time out, but takes 15 minutes (!).
while this transaction request is busy timing out, I can make subsequent requests successfully.
doesn't seem to be a starved local connection pool. I have seen this right after restarting the Tomcat.
When it finally times out (did I mention 15 minutes!) I get the following:
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Acquired Connection [org.apache.commons.dbcp.PoolableConnection#3269c671] for JDBC transaction
DEBUG: org.springframework.jdbc.datasource.DataSourceTransactionManager - Switching JDBC Connection [connection is closed] to manual commit
DEBUG: org.springframework.jdbc.datasource.DataSourceUtils - Returning JDBC Connection to DataSource
DEBUG: org.springframework.jdbc.datasource.DataSourceUtils - Could not close JDBC Connection
ERROR: java.sql.SQLException: Already closed.
ERROR: org.springframework.transaction.CannotCreateTransactionException: Could not open JDBC Connection for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed.
Caused by: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
The last packet successfully received from the server was 1,312,604 milliseconds ago. The last packet sent successfully to the server was 924,748 milliseconds ago.
Caused by: java.net.SocketException: Connection timed out
Running Spring 3.1.1, mysql 5.1.32, commons-dbcp 1.4 and commons-pool 1.5.4.
Does anyone know what this is?

Your problem is that MySQL server timeouts idle JDBC connections. This has nothing to do with the TransactionManager set-up.
Have a look at your DataSource set-up. It shall tests connection on connection retrieval and/or validate idle connections in pool.
In commons-dbcp you can set-up test on connection retrieval via the testOnBorrow and validationQuery properties.

Related

Proper setting of application properties for "No operation allowed connection" exception

Application: Java spring boot + mysql
Story:
application log showed "Could not open JDBC Connecton for transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure"
Recovery of the DB instance has been triggered since hardware problem occurred in RDS instance
After 10 mins, the recovery is done.
application log showed "Could not commit JDBC transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: No operations allowed after connection closed." instead of previous exception.
After 45 mins, application resumed normal without manual operations.
Questions:
Will restarting the application solve the problem instantly?
Manual operation might not be the best to resolve such problem. But if I want it be auto resumed shortly, anything I can do to the setting datasource properties? i.e. set spring.datasource.justswap.time-between-eviction-runs-millis shorter?
Current datasource setting:
spring.datasource.xxx.maxActive=700
spring.datasource.xxx.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.xxx.test-on-borrow=false
spring.datasource.xxx.test-while-idle=true
spring.datasource.xxx.time-between-eviction-runs-millis=3600000
spring.datasource.druid.stat-view-servlet.enabled=false

Issue integrating mariaDB client with MySQL DB

I am running a java application with MySQL as the DB server. DB is a AWS RDS. The MySQL connector is published under GNU/GPL so it has to be substituted with something more lenient. Maria DB client claimed to be compatible. But ever since MariaDB client is being used we are seeing the below intermittent issue during DB intensive activities:
Excption:-
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/Projectname] threw exception [Request processing failed; nested exception is org.springframework.transaction.CannotCreateTransactionException: Could not open Hibernate Session for transaction; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection] with root cause
java.sql.SQLNonTransientConnectionException: (conn=1530488) Connection is closed
at org.mariadb.jdbc.internal.util.exceptions.ExceptionFactory.createException(ExceptionFactory.java:73)
at org.mariadb.jdbc.internal.util.exceptions.ExceptionFactory.create(ExceptionFactory.java:187)
at org.mariadb.jdbc.internal.protocol.AbstractQueryProtocol.cmdPrologue(AbstractQueryProtocol.java:1940)
Caused by: org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection
at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:48)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:42)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:113)
Caused by: java.sql.SQLNonTransientConnectionException: Could not connect to address=(host=XXXXXXXXXX)(port=3306)(type=master) : (conn=1530487) could not load system variables
at org.mariadb.jdbc.internal.util.exceptions.ExceptionFactory.createException(ExceptionFactory.java:73)
at org.mariadb.jdbc.internal.util.exceptions.ExceptionFactory.create(ExceptionFactory.java:192)
at org.mariadb.jdbc.internal.protocol.AbstractConnectProtocol.connectWithoutProxy(AbstractConnectProtocol.java:1372)
I have tried increasing the time_wait and max_allowed_packet to the maximum allowed but the issue still exists.
Versions:-
MySQL - 5.7.26
MariaDB connector - 2.6.2
Just came across this, found an answer. On my side this was for an Aurora 1 MySQL DB (equiv to 5.6).
As per Diego Dupin in https://jira.mariadb.org/browse/CONJ-824:
only good solution is to use option `usePipelineAuth=false&useBatchMultiSend=false`
So your DB connection string might look like this:
jdbc:mysql://127.0.0.1:3307/mydbname?usePipelineAuth=false&useBatchMultiSend=false
More details:
Aurora proxy has a known race condition issue that results in skipping other
queries in proxy buffer. connection might be in hang waiting for query response.
During authentication, socket has a timeout, that will result throwing the error
you describe.
So if `usePipelineAuth` or `useBatchMultiSend` is enable, it might work ... or not.
All pipeline options (`usePipelineAuth` and `useBatchMultiSend`) must be disabled when using aurora.
Problem has been reported to aurora a few times without correction.

Connection issue while connecting to HANA DB via JDBC

I am connecting HANA DB via ngdbc.jar. Connection is made properly but after running query 3-4 times connection to HANA DB is lost. When I restart my JAVA server again it works for 3-4 times. Can anyone help?
Error Msg-
WARN [org.hibernate.util.JDBCExceptionReporter] (http--0.0.0.0-8080-6) SQL Error: -708, SQLState: 08006
ERROR [org.hibernate.util.JDBCExceptionReporter] (http--0.0.0.0-8080-6) Data receive failed [Connection reset].
INFO [com.ultimatix.controller.MetricsController] (http--0.0.0.0-8080-6) context setMonthFreezeDateorg.hibernate.exception.JDBCConnectionException: could not execute query
ERROR [org.hibernate.transaction.JDBCTransaction] (http--0.0.0.0-8080-6) JDBC rollback failed: com.sap.db.jdbc.exceptions.jdbc40.SQLNonTransientConnectionException: Connection to database server lost; check server and network status [System error: Socket closed]
I can see you are using Hibernate based on your log.
Can you elaborate a little bit on your stack?
As #RC said, you should consider connection pooling instead of opening direct connections if this is what you are doing in your "JAVA" server.
May be your are keeping the connection open for too long and it times out.
These are all guesses, until you can share any logs or sample code.
One more thing, related to the ngjdbc driver only, there is a "reconnect" connection property which by default is set to false.
Regards

org.springframework.jdbc.CannotGetJdbcConnectionException

I am working in spring3 project. When I run my code sometimes i am getting this Jdbc Connection Exception for some particular functionality but other functionalities working very fine. And also this Exception is not occurring repetitively but sometimes, So I can't get where the mistake will be.
Please help me to come out of this problem.
<[weblogic.servlet.internal.WebAppServletContext#1b6e978 - appName: '_auto_generated_ear_', name: 'ae', context-path: '/ae'] Root cause of ServletException.
org.springframework.jdbc.CannotGetJdbcConnectionException: Could not get JDBC Connection; nested exception is java.sql.SQLException: Listener refused the connection with the following error:
ORA-12519, TNS:no appropriate service handler found
The Connection descriptor used by the client was:
localhost:1521:XE at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:80)
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:573)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:637)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:666)
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:674)
Truncated. see log file for complete stacktrace
java.sql.SQLException: Listener refused the connection with the following error:
ORA-12519, TNS:no appropriate service handler found
The Connection descriptor used by the client was:
localhost:1521:XE
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112)
at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:261)
at oracle.jdbc.driver.T4CConnection.logon(T4CConnection.java:387)
at oracle.jdbc.driver.PhysicalConnection.(PhysicalConnection.java:420)
at oracle.jdbc.driver.T4CConnection.(T4CConnection.java:165)
Truncated. see log file for complete stacktrace
There are 2 common reason for that symptoms
The connection pool is exhausted, too many active connections open and the next client cannot get it. This might be a connection pool leak
The connection pool setting doesn't test idle connection periodically / on borrow, hence when TCP connection truncated by OS (eg: because the OS thinks it's idle doing nothing), the pool still thinks it's a valid
To resolve this issue, just Restart your MySQL service
How to restart the MySQL service
On Windows: https://www.mysqltutorial.org/mysql-adminsitration/restart-mysql
On Linux:    https://linuxhint.com/restart-mysql-in-ubuntu/

Could not toggle autocommit

I have a transaction which runs for many hours in the Java Layer and the when Hibernate tries persist collated data, Exception Stack trace shown below is thrown.
Note: I have also tried the configurations specified at..
http://forums.mysql.com/read.php?39,52805,205216#msg-205216 and http://forums.mysql.com/read.php?39,52805,273371#msg-273371
++++++
ERROR org.hibernate.transaction.JDBCTransaction (JDBCTransaction.java:232) - Could not toggle autocommit
java.sql.SQLException: No operations allowed after connection closed.Connection was implicitly closed due to underlying exception/error:
** BEGIN NESTED EXCEPTION **
com.mysql.jdbc.CommunicationsException
MESSAGE: Communications link failure due to underlying exception:
** BEGIN NESTED EXCEPTION **
java.io.EOFException
STACKTRACE:
java.io.EOFException
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1903)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2349)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2860)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1571)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1666)
at com.mysql.jdbc.Connection.execSQL(Connection.java:2972)
at com.mysql.jdbc.Connection.commit(Connection.java:2147)
at org.apache.commons.dbcp.DelegatingConnection.commit(DelegatingConnection.java:301)
at org.apache.commons.dbcp.PoolingDataSource$PoolGuardConnectionWrapper.commit(PoolingDataSource.java:200)
at org.hibernate.transaction.JDBCTransaction.commitAndResetAutoCommit(JDBCTransaction.java:170)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:146)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:394)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:117)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625)
MySQL has a default timeout period after which it terminates idle connections. By default the period is 8 hrs.
The DBCP however is unaware of when the connections are terminated by the MySQL server and so these stale connections are still handed out on demand to the application. Hence you get an Exception.
A fix is to add the following properties to your dbcp config:
validationQuery=”SELECT 1″
testOnBorrow=”true”
This tells DBCP to validate the connection with that query.
The connection was most likely dropped by the database. Specify a validation query on DBCP to ensure that the connections in the pool are still alive.
http://commons.apache.org/dbcp/configuration.html
We were having a very similar stacktrace at work when trying to index data, using Lucene, from our Spring application. The problem was the wait_timeout setting in my.cnf. We had just upgraded our MySQL installation and our DBA had forgotten to change wait_timeout from the default setting to what it was previously, 3600.

Categories