当我在1秒内触发10个请求时,就会发生org.springframework.dao.CannotAcquireLockException。
尽管我用@Transactional(isolation = Isolation.SERIALIZABLE)标记了我的主要方法(调用存储库方法),而存储库中的findBy方法有@Lock(LockModeType.PESSIMISTIC_WRITE)注释。
在一个环境中,一切正常工作,但在另一个环境中,会发生错误。知道为什么会出现错误吗?两种环境下的代码是相同的。
Stacktrace 1:
{“时间戳”:“2017-08-21T12:18:16.16+0000”,"status":500,“Error”:“"exception":"org.springframework.orm.jpa.JpaSystemException",Server Error","com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:"message":试图锁定时发现的”com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:死锁;尝试重新启动事务;嵌套异常是在尝试锁定时发现的javax.persistence.PersistenceException: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:死锁;尝试重新启动事务“,”路径“:”/car/toyota“}
Stacktrace 2:
{“时间戳”:“2017-08-21T12:11:57.57+0000”、“状态”:500、“错误”:“内部服务器错误”、"exception":"org.springframework.dao.CannotAcquireLockException",“消息”:“无法执行语句;SQL /a;嵌套异常是org.hibernate.exception.LockAcquisitionException:无法执行语句”、“路径”:“/cars/丰田”}
发布于 2017-08-22 12:58:03
当您试图锁定一行时,会引发错误,但该行已被另一个事务锁定。所以超时就会发生。
添加@Transactional(isolation = Isolation.SERIALIZABLE)使情况更加糟糕,因为可序列化级别意味着一个事务锁定整个表(现代甲骨文可以控制这一点,但对于MySQl,它实际上是一个等待锁定同一个表的事务队列)。因此,第十个事务等待所有前面的9个事务,然后失败。
实际上,我不明白为什么需要findBy方法上的锁。从逻辑上讲,该方法不应该修改表,因此根本不需要锁定。
如果您有并发修改,我建议更改逻辑,使单个调用更快,甚至引入乐观锁(基于版本)。Hibernate通过添加@Version来实现这一点。
https://stackoverflow.com/questions/45818084
复制相似问题