@Override
@Transactional
public ClassA executeFun(ClassC c ,ClassD d){
ClassB b = new ClassB();
保存b;
更新c;
更新d;
}
当service接口方法实现类代码执行完进行事务提交时抛出(更新c的死锁)异常:org.springframework.orm.jpa.JpaSystemException: org.hibernate.exception.LockAcquisitionException: Deadlock found when trying to get lock; try restarting transaction; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.LockAcquisitionException: Deadlock found when trying to get lock; try restarting transaction
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.LockAcquisitionException: Deadlock found when trying to get lock; try restarting transaction
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1387)
at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1310)
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:80)
at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:512)
... 52 more
Caused by: org.hibernate.exception.LockAcquisitionException: Deadlock found when trying to get lock; try restarting transaction
at org.hibernate.dialect.MySQLDialect$1.convert(MySQLDialect.java:392)
at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
at com.sun.proxy.$Proxy632.executeUpdate(Unknown Source)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3189)
at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:3087)
at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:3416)
at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:140)
at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:276)
at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213)
at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402)
at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:75)
... 53 more
Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
at com.mysql.jdbc.Util.getInstance(Util.java:386)
at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1066)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4187)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4119)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2815)
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2458)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2375)
at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2359)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)
... 69 more
出现的结果就是:
更新对象ClassB的事务没有回滚;更新对象ClasssC的事务回滚了;更新对象ClassD的事务回滚了。
注:1、数据库是mysql innodb;
2、抛出的异常(死锁异常)是运行时异常;
@Override
@Transactional
public ClassA executeFun(ClassC c ,ClassD d){
ClassB b = new ClassB();
保存b;
更新c;
更新d;
}
这段代码,如果"更新c;"这句抛了异常,那么"更新d;"也就不会执行了吧,
既然没有执行"更新d;",那么也就谈不上“更新对象ClassD的事务回滚了”。
此外,更新c的死锁,那么也就是说没有对c进行更新,也谈不上“更新对象ClasssC的事务回滚了”。
无论如何,同一事务中后续代码抛了异常,前边数据库操作不应该不回滚,因此我怀疑你的 spring 事务控制压根儿就没起作用。
#4
这句话有所欠妥。
MySQL 的存储引擎不是在建库时定义的,是在建表 DDL 时声明的,同库里可以有多种类型的存储引擎的表,每个表的存储引擎未必一致。
如果你的 spring 事务配置没问题,我怀疑是你的类 B 对应的表存储引擎可能是 MyISAM 所致。
查看你的实体类 B 对应的表(比如是 TABLE_B)的存储引擎是否是 InnoDB:
SHOW CREATE TABLE TABLE_B;
如果结果是 ENGINE=MyISAM,那么就是它的原因了。
既然没有执行"更新d;",那么也就谈不上“更新对象ClassD的事务回滚了”。
此外,更新c的死锁,那么也就是说没有对c进行更新,也谈不上“更新对象ClasssC的事务回滚了”。
无论如何,同一事务中后续代码抛了异常,前边数据库操作不应该不回滚,因此我怀疑你的 spring 事务控制压根儿就没起作用。
#4
注:1、数据库是mysql innodb;
这句话有所欠妥。
MySQL 的存储引擎不是在建库时定义的,是在建表 DDL 时声明的,同库里可以有多种类型的存储引擎的表,每个表的存储引擎未必一致。
如果你的 spring 事务配置没问题,我怀疑是你的类 B 对应的表存储引擎可能是 MyISAM 所致。
查看你的实体类 B 对应的表(比如是 TABLE_B)的存储引擎是否是 InnoDB:
SHOW CREATE TABLE TABLE_B;
如果结果是 ENGINE=MyISAM,那么就是它的原因了。
#5
注:1、数据库是mysql innodb;
这句话有所欠妥。
MySQL 的存储引擎不是在建库时定义的,是在建表 DDL 时声明的,同库里可以有多种类型的存储引擎的表,每个表的存储引擎未必一致。
如果你的 spring 事务配置没问题,我怀疑是你的类 B 对应的表存储引擎可能是 MyISAM 所致。
查看你的实体类 B 对应的表(比如是 TABLE_B)的存储引擎是否是 InnoDB:
SHOW CREATE TABLE TABLE_B;
如果结果是 ENGINE=MyISAM,那么就是它的原因了。