我尝试使用spring boot,spring data和mysql来理解事务。
我创建了服务UpdateService,用于更新数据库中的记录。方法change和change2以事务方式执行。
@Autowired
private UserRepo userRepo;
@Transactional(isolation = Isolation.SERIALIZABLE)
public void change() {
User user = userRepo.findOne("Jan");
write("before change", user);
sleep(2000);
user.setPassword("new password");
write("after change", user);
}
@Transactional(isolation = Isolation.SERIALIZABLE)
public void change2() {
User user = userRepo.findOne("Jan");
write("before change2", user);
user.setSecondName("new name");
write("after change2", user);
}
当我调用change和change2方法时,我收到了日志:
before change User(name=Jan, secondName=Adam, password=Kowalski)
before change2 User(name=Jan, secondName=Adam, password=Kowalski)
after change2 User(name=Jan, secondName=new name, password=Kowalski)
after change User(name=Jan, secondName=Adam, password=new password)
之后我也得到了例外:
com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
我的问题是为什么交易更改2在更改完成之前就开始了?死锁的原因是什么?
答案 0 :(得分:2)
贝娄是我的观点:
为什么交易更改2在更改完成之前就开始了?
对于mysql,首先需要关心 MySQL的版本,并查看this official site url about transaction。特别是,隔离级别 SERIALIZABLE :
的描述死锁的原因是什么?
当执行更改和更改2 的读取操作时,表示两个交易在同一行上保留共享锁。当执行更改(事务t1)和更改2 (事务t2)的写入操作时,t1将在t2上等待释放共享锁并且t2也将等待t1释放共享锁,这将导致死锁。
我建议你看看MySQL的交易和锁定机制:
http://dev.mysql.com/doc/refman/5.7/en/innodb-transaction-model.html http://dev.mysql.com/doc/refman/5.7/en/innodb-lock-modes.html
希望能帮到你。