当我在1秒内触发10个请求时,org.springframework.dao.CannotAcquireLockException
发生。
即使我用@Transactional(isolation = Isolation.SERIALIZABLE)
标记了我的main方法(在里面调用存储库方法),我的存储库中的findBy方法也有@Lock(LockModeType.PESSIMISTIC_WRITE)
注释。
在一个环境中一切正常,但在另一个环境中发生错误。任何想法错误发生的想法?两种环境下的代码都是相同的。
Stacktrace 1:
{"时间戳":" 2017-08-21T12:18:16.16 + 0000""状态" 500"错误&#34 ;:"内部服务器错误","例外":" 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"错误&#34 ;:"内部服务器错误","例外":" org.springframework.dao.CannotAcquireLockException"," message":"无法执行声明; SQL [不适用]; 嵌套异常是org.hibernate.exception.LockAcquisitionException:无法执行语句"," path":" / cars / toyota"}
答案 0 :(得分:1)
当您尝试锁定行但该行已被另一个事务锁定时,会引发错误。所以超时发生了。
添加foreach (var employee in model.Employees)
{
if (employee.Selected == true)
{
var commissionemployeeposition = new CommissionEmployeePosition();
commissionemployeeposition.CommissionId = commission.Id;
commissionemployeeposition.EmployeeId = employee.Id;
if (model.SupervisorID == commissionemployeeposition.EmployeeId)
commissionemployeeposition.EmployeePositionId = (int)Position.Supervisor;
else
commissionemployeeposition.EmployeePositionId = (int)Position.Member;
//commission.CommissionEmployeePositions.Add(commissionemployeeposition);
unitOfWork.CommissionEmployeePositionRepository.Insert(commissionemployeeposition);
}
}
会使情况变得更糟,因为可序列化级别意味着一个事务锁定整个表(现代oracle可以某种方式控制它,但对于MySQl,它实际上是一个等待锁定同一个表的事务队列)。因此,第10次交易等待所有之前的9次交易并失败。
实际上我不明白为什么你需要锁定public class CommissionEmployeePosition
{
public int CommissionId { get; set; }
public int EmployeeId { get; set; }
public int EmployeePositionId { get; set; }
public Commission Commission { get; set; }
public Employee Employee { get; set; }
public EmployeePosition EmployeePosition { get; set; }
}
方法。从逻辑上讲,该方法不应该修改表,因此根本不需要锁定。
如果您有并发修改,我建议更改逻辑以更快地进行一次调用,甚至引入乐观锁(基于版本)。 Hibernate允许添加@Transactional(isolation = Isolation.SERIALIZABLE)
。