A few days passed when I had problems blocking a Java application with Glassfish - EJB3 with Mysql InnoDB
Config: Mysql InnoDB: version 14.12. Distribution 5.0.51a, for debian-linux-gnu (i486) using readline 5.2
Application Server: Glassfish v2.1
Persistence with EJB3 - JPA - Hibernate
To make this simple, I have - an SOA system with servlets that process user subscriptions for services, login, logout, payments and registration, etc ... - a quartz work system (cron triggers), which process the daily decline of these services, the generation of "low credit" alerts, confirmation of payments, etc.
My problem: during load checks, I found deadlocks (100,000 users - 30 requests per second)
Returned Stack Sample:
Message ID: Could not synchronize database state with session org.hibernate.exception.LockAcquisitionException Complete Message: Could not execute JDBC batch update at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:105) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275) at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:114) at org.hibernate.jdbc.AbstractBatcher.prepareStatement(AbstractBatcher.java:109) at org.hibernate.jdbc.AbstractBatcher.prepareBatchStatement(AbstractBatcher.java:244) at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2382) at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2335) at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2635) at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:115) at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:279) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:263) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168) at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) at org.hibernate.event.def.DefaultAutoFlushEventListener.onAutoFlush(DefaultAutoFlushEventListener.java:64) at org.hibernate.impl.SessionImpl.autoFlushIfRequired(SessionImpl.java:996) at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1141) at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102) at org.hibernate.ejb.QueryImpl.getResultList(QueryImpl.java:67) at net.xxx.server.dao.impl.PaymentDAOImpl.listPaymentsByStateAndCompany(PaymentDAOImpl.java:270)
Pay attention to the end, this is the code I made: net.xxx.server.dao.impl.PaymentDAOImpl.listPaymentsByStateAndCompany (PaymentDAOImpl.java:270)
This function:
private static final String QUERY_FOR_PAYMENTS_BY_STATE_AND_COMPANY = " FROM " + Payment.class.getName() + " p WHERE p.serviceDefinition.company=:company" + " AND p.state = :state"; @SuppressWarnings("unchecked") public List<Payment> listPaymentsByStateAndCompany(Company company,Constants.PaymentState state) { List<Payment> payments = this.getEntityManager() .createQuery(QUERY_FOR_PAYMENTS_BY_STATE_AND_COMPANY) .setParameter("state",state.ordinal()) .setParameter("company",company) .getResultList(); return payments; }
This function works great when it does not load testing, and that we have 1 request every 5 seconds, for example.
During load testing, we have tasks that work with high frequencies (for example, every 5 seconds).
I do not get only this error, but some others on other tasks too (still a dead end)!
On MYSQL:
Dead end example:
------------------------ LATEST DETECTED DEADLOCK ------------------------ 090428 12:21:11 *** (1) TRANSACTION: TRANSACTION 0 14286818, ACTIVE 0 sec, process no 21872, OS thread id 802850 starting index read mysql tables in use 1, locked 1 LOCK WAIT 13 lock struct(s), heap size 1024, undo log entries 2 MySQL thread id 298, query id 11843357 localhost 127.0.0.1 root Updating update service set balance=40.0, company_id=2, last_on='2009-04-28 12:19:55', modified_by='server', modified_on='2009-04-28 12:21:11', service_definition_id=3, state=1, subscriber_id=13578, valid_until='2010-02-22 12:13:52' where service_id=693 *** (1) WAITING FOR THIS LOCK TO BE GRANTED: RECORD LOCKS space id 0 page no 62 n bits 176 index `PRIMARY` of table `xxx/service` trx id 0 14286818 lock_mode X locks rec but not gap waiting Record lock, heap no 98 PHYSICAL RECORD: n_fields 12; compact format; info bits 0 0: len 8; hex 80000000000002b5; asc ;; 1: len 6; hex 000000d9faa0; asc ;; 2: len 7; hex 0000000cc91e70; asc p;; 3: len 4; hex 00001c42; asc B;; 4: len 8; hex 80001245aad4e363; asc E c;; 5: len 6; hex 736572766572; asc server;; 6: len 8; hex 80001245aad4e3c9; asc E ;; 7: len 1; hex 81; asc ;; 8: len 8; hex 80001247f200df08; asc G ;; 9: len 8; hex 8000000000000002; asc ;; 10: len 8; hex 8000000000000003; asc ;; 11: len 8; hex 800000000000350a; asc 5 ;; *** (2) TRANSACTION: TRANSACTION 0 14286798, ACTIVE 1 sec, process no 24963, OS thread id 393239 starting index read, thread declared inside InnoDB 500 mysql tables in use 1, locked 1 17 lock struct(s), heap size 1024, undo log entries 16 MySQL thread id 253, query id 11843359 localhost 127.0.0.1 root Updating update payment set credit=1.0, currency='EUR', modified_by='9999900092', modified_on='2009-04-28 12:21:11', payment_definition_id=7, price=1.0, service_definition_id=3, state=0, subscriber_id=13578, transaction_id=11463 where payment_id=15914 *** (2) HOLDS THE LOCK(S): RECORD LOCKS space id 0 page no 62 n bits 176 index `PRIMARY` of table `xxx/service` trx id 0 14286798 lock mode S locks rec but not gap Record lock, heap no 47 PHYSICAL RECORD: n_fields 12; compact format; info bits 0 0: len 8; hex 8000000000000286; asc ;; 1: len 6; hex 000000d9ffce; asc ;; 2: len 7; hex 0000000cc90683; asc ;; 3: len 4; hex 0000f841; asc A;; 4: len 8; hex 80001245aad4e3b2; asc E ;; 5: len 6; hex 736572766572; asc server;; 6: len 8; hex 80001245aad4e3ff; asc E ;; 7: len 1; hex 81; asc ;; 8: len 8; hex 80001245d450fed8; asc EP ;; 9: len 8; hex 8000000000000002; asc ;; 10: len 8; hex 8000000000000003; asc ;; 11: len 8; hex 80000000000034db; asc 4 ;;
Transaction Isolation
I read transaction isolation information on the Internet.
On a glass planet, we can set the transaction isolation level, I put it uncommitted.
This did not work, then I installed the same level in mysql:
mysql> SELECT @@global.tx_isolation; +-----------------------+ | @@global.tx_isolation | +-----------------------+ | READ-UNCOMMITTED | +-----------------------+ 1 row in set (0.00 sec) mysql> SELECT @@tx_isolation; +------------------+ | @@tx_isolation | +------------------+ | READ-UNCOMMITTED | +------------------+ 1 row in set (0.00 sec)
SVP can someone tell me what could be the problem? I really do not know!!!!
BTW, which I saw on the Internet, you can select the transaction isolation level for each request ... Is it possible to set the transaction isolation level for methods on JPA directly? Because I think that only jobs that perform global data updates (for example, reducing 15,000 services) should be read-uncommitted, am I mistaken?