Java 即使使用LockModeType.悲观_写入也会死锁
当我在1秒内触发10个请求时,Java 即使使用LockModeType.悲观_写入也会死锁,java,spring,hibernate,spring-data-jpa,Java,Spring,Hibernate,Spring Data Jpa,当我在1秒内触发10个请求时,org.springframework.dao.CannotAcquireLockException 发生 尽管我用@Transactional(isolation=isolation.SERIALIZABLE)标记了我的主方法(在内部调用存储库方法),并且存储库中的findBy方法具有@Lock(LockModeType.悲观的_-WRITE)注释 在一个环境中,一切正常,但在另一个环境中,会发生错误。知道为什么会发生错误吗?这两种环境中的代码是相同的 Stack
org.springframework.dao.CannotAcquireLockException
发生
尽管我用@Transactional(isolation=isolation.SERIALIZABLE)
标记了我的主方法(在内部调用存储库方法),并且存储库中的findBy方法具有@Lock(LockModeType.悲观的_-WRITE)
注释
在一个环境中,一切正常,但在另一个环境中,会发生错误。知道为什么会发生错误吗?这两种环境中的代码是相同的
Stacktrace 1:
{“时间戳”:“2017-08-21T12:18:16.16+0000”,“状态”:500,“错误”:“内部服务器错误”,“异常”:“org.springframework.orm.jpa.JpaSystemException”,“消息”:
“com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:尝试获取锁时发现死锁;尝试重新启动事务;嵌套异常为
javax.persistence.PersistenceException:com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:尝试获取锁时发现死锁;请尝试重新启动
交易记录,“路径”:“/汽车/丰田”}
Stacktrace 2:
{“时间戳”:“2017-08-21T12:11:57.57+0000”,“状态”:500,“错误”:“内部服务器错误”,“异常”:“org.springframework.dao.CannotAcquireLockException”,“消息”:“无法执行语句;SQL[n/a];
嵌套异常为org.hibernate.exception.LockAcquisitionException:无法执行语句,“路径”:“/cars/toyota”}
当您尝试锁定一行,但该行已被另一个事务锁定时,将引发该错误。所以超时发生了 添加
@Transactional(isolation=isolation.SERIALIZABLE)
会使情况变得更糟,因为可序列化级别意味着一个事务会锁定整个表(现代oracle可以以某种方式控制这一点,但对于MySQl来说,它实际上是一个等待锁定同一表的事务队列)。所以第10个事务等待前9个事务并失败
事实上,我不明白为什么需要通过方法查找上的锁。从逻辑上讲,该方法不应该修改表,因此根本不需要锁定
我建议更改逻辑,使单个调用更快,或者如果同时进行修改,甚至引入乐观锁(基于版本)。Hibernate通过添加您使用的@Version
数据库?MySQL数据库来实现这一点。我忘了提了,对不起。你还有一些其他的线索。。。可能需要包括,我刚刚粘贴了两个StackTrace,两个都是出于相同的原因发生的。一个由jdbc处理程序捕获,另一个由hibernate处理程序捕获并由Spring抛出。大逻辑块要求在事务完成之前锁定该行。甚至为了防止从那一行读取。我只是想知道如何防止这种僵局@Transactional不会锁定整个表,因为其他行上的事务工作正常。只是同一行上的事务正在制造麻烦。