MyBatisPlus:IService接口的saveBatch方法使用不当导致死锁

star2017 1年前 ⋅ 1510 阅读

MyBatis Plus:IService接口的saveBatch方法使用不当导致死锁。

补充:2021-01-14
之前的描述不严谨,Spring 事务还有个属性是 传播行为,默认是 PROPAGATION_REQUIRED,如果当前没有事务,则新建一个事务。
也就是本篇描述的问题还待深入研究,查问题确实存在。

问题

看起来的一个简单的更新方法,但导致了死锁,查看数据库事务日志,也没有其它SQL开启事务,但存在等待锁的事务。

业务

一个更新的业务,有一张主表,两个关联表。在一个更新的方法中,先修改主表,删除两个关联表数据,然后再插入新的数据到两个关联表。

  1. 在更新的方法上开启了事务。
  2. 插入新数据调了 Mybatis-Plus IService 接口的 saveBatch 方法来执行批量插入。

原因

根本原因就是更新方法开启了事务占用锁,内部调了 IService 接口的 saveBatch 方法来执行批量插入。

  1. 外层更新方法开启事务持有锁。
  2. 内部调了 saveBatch 来执行批量插入,而 Mybatis-Plus 的 IService 接口的 saveBatch 方法也是会开启事务的,就需要持有锁,但锁被外层事务占用,就会一直等待锁。
  3. 外层方法事务需要正常结束才会释放锁,而内部 saveBatch 会一直等待就不能正常结束。
  4. 这样就出现了死锁:即 A 等 B 正常结束才释放锁,而 B 必须先拿到锁才能正常结束。
  5. 直到 saveBatch 事务等待锁超时抛出异常才终止。

解决

在 XML Mapper 文件,使用 foreach 手写批量插入的SQL。不使用 Mybatis-Plus IService 接口的 saveBatch 方法。

更多内容请访问:IT源点

相关文章推荐

全部评论: 0

    我有话说: