Atomikos Forum |
|
Hi,
First, congrats for the great product! In our application we use Spring 2.5.5, Atomikos 3.5.4 and EclipseLink 1.1.0 as JPA provider on MySQL 5.0.60 (with mysql-connector 5.1.6). We tried to use both deprecated NonXADataSourceBean and AtomikosNonXADataSourceBean and observed the following behaviour: 1. In configuration With NonXADataSourceBean user sometimes sees stale data while working with the application - for example newly created items are appearing/disappearing from the list when user refreshes it few times. This occurs most likely depending on the connection obtained from the pool - some still see stale data. Our assumption is that it could be because db transaction on that connection was somehow started long ago (we use REPEATABLE READ as MySQL transaction isolation level). When we set poolSize=0, db connection is opened/closed everytime and we do not have stale data problems anymore.
2. In configuration with AtomikosNonXADataSourceBean we do not have stale data problems, but sometimes obtain heuristic exceptions (few times per thousand transactions) when we load test the application (we never obtain these with NonXADataSourceBean). These are some examples from atomikos log file:
09-04-29 14:19:35,803 [Atomikos:21] Error in non-XA commit com.atomikos.jdbc.AtomikosSQLException: Error in commit on vendor connection at com.atomikos.jdbc.AtomikosSQLException.throwAtomikosSQLException(AtomikosSQLException.java:19) at com.atomikos.jdbc.nonxa.AtomikosThreadLocalConnection.transactionTerminated(AtomikosThreadLocalConnection.java:370) at com.atomikos.jdbc.nonxa.AtomikosNonXAParticipant.commit(AtomikosNonXAParticipant.java:112) at com.atomikos.icatch.imp.CommitMessage.send(CommitMessage.java:94) at com.atomikos.icatch.imp.PropagationMessage.submit(PropagationMessage.java:86) at com.atomikos.icatch.imp.Propagator$PropagatorThread.run(Propagator.java:62) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:619) Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Connection.close() has already been called. Invalid operation in this state. at ... , also: 09-04-29 14:19:25,788 [Atomikos:21] Error in non-XA commit com.atomikos.jdbc.AtomikosSQLException: Error in commit on vendor connection at com.atomikos.jdbc.AtomikosSQLException.throwAtomikosSQLException(AtomikosSQLException.java:19) at com.atomikos.jdbc.nonxa.AtomikosThreadLocalConnection.transactionTerminated(AtomikosThreadLocalConnection.java:370) at com.atomikos.jdbc.nonxa.AtomikosNonXAParticipant.commit(AtomikosNonXAParticipant.java:112) at com.atomikos.icatch.imp.CommitMessage.send(CommitMessage.java:94) at com.atomikos.icatch.imp.PropagationMessage.submit(PropagationMessage.java:86) at com.atomikos.icatch.imp.Propagator$PropagatorThread.run(Propagator.java:62) at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908) at java.lang.Thread.run(Thread.java:619) Caused by: java.sql.SQLException: Can't call commit when autocommit=true at ...
More detailed configuration:
<bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager" ref="AtomikosTxMgr" /> <property name="userTransaction" ref="AtomikosUsrTx" /> <property name="transactionSynchronizationName" value="SYNCHRONIZATION_ON_ACTUAL_TRANSACTION" /> <property name="allowCustomIsolationLevels" value="true" /> </bean> <bean id="transactionSessionCustomizer" class="com.s4hc.bes.dao.eclipselink.TransactionSessionCustomizer" scope="prototype"> <property name="transactionManager" ref="transactionManager" /> </bean> <bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="jpaProperties"> <props> ... <!-- pass transaction manager to eclipselink --> <prop key="eclipselink.session.customizer">com.s4hc.bes.dao.eclipselink.TransactionSessionCustomizer</prop> </props> </property> ... </bean>
with variants of data sources:
1. <bean id="dataSource" class="com.atomikos.jdbc.nonxa.NonXADataSourceBean"> <property name="user" value="${jdbc.user}" /> <property name="password" value="${jdbc.password}" /> <property name="url" value="${jdbc.url}" /> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="poolSize" value="0" /> <property name="testOnBorrow" value="true" /> </bean> 2. <bean id="dataSource" class="com.atomikos.jdbc.nonxa.AtomikosNonXADataSourceBean"> <property name="uniqueResourceName" value="NONXADBMS" /> <property name="user" value="${jdbc.user}" /> <property name="password" value="${jdbc.password}" /> <property name="url" value="${jdbc.url}" /> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="poolSize" value="100" /> <property name="testQuery" value="SELECT 1" /> <property name="reapTimeout" value="0" /> </bean> So, we are currently using NonXADataSourceBean (poolSize = 0) and do not have much performance problems with lack of pooling for db connections. However, it would be nice if we could use any of the variants with connection pooling. Cheers, Misa
When it comes to NonXADS/stale data issue, I tried to reproduce the problem with a simple test, but did not succeed.
I set poolSize=2 and used Atomikos transaction API and JDBC via mysql-connector, and did something like: 1.select -from thread 1 with conn1 2.insert -from thread 2 with conn2 3.select -from thread 3 with conn1 If my assumption had been correct, third select would not have seen the inserted data. I tried to simulate some hidden selects on the connection proxy that could produce the problem, but either exception was thrown or everything worked fine. However, our application does not have stale data problem with JPATransactionManager/DBCP and AtomikosNonXADS, which led me to this assumption in the first place.
With AtomikosNonXADS, I could barely assume anything. I looked at the logs produced by our application during load testing simulating 25 users simultaneously accessing it for some time and found some exceptions both on reads and writes (updates).
What I didn't notice before, and seems to be rather consequence then cause (since it happens after some pure DB exceptions) is one exception involving JMS: AtomikosNONXADS:JMS: driver complains while enforcing XA mode - ignore if no later errors: javax.jms.TransactionInProgressException: Cannot rollback() inside an XASession at org.apache.activemq.ActiveMQXASession.rollback(ActiveMQXASession.java :76) at com.atomikos.jms.DefaultJtaConnection.forceConnectionIntoXaMode(Defau ltJtaConnection.java:39) at com.atomikos.jms.JtaQueueConnection.createQueueSession(JtaQueueConnec tion.java:54) at com.atomikos.jms.JtaQueueConnection.createSession(JtaQueueConnection. java:77)
AtomikosNONXADS before JMS in the previous post is typo - please disregard it.
If it is of interest, we use ActiveMQ 5.1 and our JMS config is the following: <bean id="jmsFactory" class="com.atomikos.jms.QueueConnectionFactoryBean" init-method="init"> <property name="resourceName" value="amq1" /> <property name="xaQueueConnectionFactory" ref="xaFactory" /> </bean> <bean id="queueListenerContainer" abstract="true" class="org.springframework.jms.listener.DefaultMessageListenerContainer"> <property name="transactionManager" ref="transactionManager" /> <property name="connectionFactory" ref="jmsFactory" /> <property name="concurrentConsumers" value="1" /> <property name="maxConcurrentConsumers" value="1" /> <property name="sessionTransacted" value="true" /> <property name="cacheLevel" value="3" /> </bean> We cache JMS connections, sessions and listeners to avoid performance problems. We also tried the newer connection factory bean with jms pooling, but we had some issues - and stayed with this one. Cheers |