Bonjour,
J'aimerais avoir des retours d'expérience sur la façon dont vous gérez les différents locks.
Pour faire des tests j'ai plein de threads qui accèdent tous à la même ligne de la même table en même temps, et qui incrémentent un compteur sur cette ligne.
Résultats du test ;
Si je met pas transaction-isolation=SERIALIZABLE dans mysql, il n'y a aucun problème en java mais à la fin du test le compteur n'a pas la bonne valeur. Ceci n'est bien sûr pas souhaitable, ça veut dire qu'un thread n'a pas tenu compte de la modification d'un autre. On garde donc transaction-isolation=SERIALIZABLE.
Ensuite si je relance ce test j'ai beaucoup d'exceptions du type :
Code:
2005-10-12 18:25:11,243 [Thread-12] WARN org.hibernate.util.JDBCExceptionReporter:71 - SQL Error: 1213, SQLState: 40001
2005-10-12 18:25:11,243 [Thread-12] ERROR org.hibernate.util.JDBCExceptionReporter:72 - Deadlock found when trying to get lock; try restarting transaction
2005-10-12 18:25:11,245 [Thread-12] ERROR org.hibernate.event.def.AbstractFlushingEventListener:277 - Could not synchronize database state with session
org.hibernate.exception.LockAcquisitionException: could not update: [tests.TestBean#25156]
at org.hibernate.exception.ErrorCodeConverter.convert(ErrorCodeConverter.java:77)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.persister.entity.BasicEntityPersister.update(BasicEntityPersister.java:2000)
at org.hibernate.persister.entity.BasicEntityPersister.updateOrInsert(BasicEntityPersister.java:1909)
at org.hibernate.persister.entity.BasicEntityPersister.update(BasicEntityPersister.java:2149)
at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:75)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:239)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:223)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:137)
at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)
at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:730)
at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:324)
at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)
at tests.Test.doRead(Test.java:95)
at tests.Test.run(Test.java:56)
Caused by: java.sql.SQLException: Deadlock found when trying to get lock; try restarting transaction
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2921)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1570)
at com.mysql.jdbc.ServerPreparedStatement.serverExecute(ServerPreparedStatement.java:1085)
at com.mysql.jdbc.ServerPreparedStatement.executeInternal(ServerPreparedStatement.java:670)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1159)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1076)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1061)
at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:22)
at org.hibernate.persister.entity.BasicEntityPersister.update(BasicEntityPersister.java:1982)
... 13 more
Certains threads ne peuvent donc pas enregistrer leurs modifications.
J'ai donc essayé de mettre un synchronized sur un mutex autour des transactions hibernate.
Cette fois ça marche mais ça limite l'intêret du pool de connexions (c'est pareil que si on en avait qu'une dans ce cas), et surtout si je regarde le temps que les threads attendent c'est beaucoup trop long pour certains (la fameuse famine des philosophes).
J'aimerais donc avoir vos conseils sur la façon de gérer ce cas.
Merci d'avance.