美文网首页
记一次由@Transactional+线程池+Future共同引

记一次由@Transactional+线程池+Future共同引

作者: 叫我民哥L | 来源:发表于2018-11-27 20:49 被阅读0次

    故事背景
    前段时间,提测前夜,某同学的代码出现了史无前例的数据库死锁问题,异常信息如下:
    org.springframework.dao.CannotAcquireLockException:

    Error updating database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

    The error may involve defaultParameterMap

    The error occurred while setting parameters

    SQL: DELETE FROM t_user WHERE user_id =?

    Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

    ; SQL []; Lock wait timeout exceeded; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction

    Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
    大概意思是等待获取数据库锁超时,目测跟事务有关系。由于当时已经凌晨,又急于解决问题,于是某同学把所有调用链的@Transaction都去掉,再试就好了,于是愉快的提测。

    时隔多日,也没找出来具体原因是啥。于是,今天找当事人还原了一下事故现场,下面是一个大概的调用链:
    A类有标注了@Transaction public方法a,作为请求入口,在此方法内对x表做update操作,然后调用同类的private方法b
    private b对数据做了一些处理,然后用Executor对资源id做处理,将id传给B类的public c方法,并将Callable的Future对象返回
    B类c方法同样标注了@Transactional,并对x表做delete操作
    在A类 private b方法,收集到Future对象后,对List<Future>集合遍历做Future.get操作,阻塞到线程池的任务全部执行结束,继续后续的逻辑处理
    于是,我按照这个调用链写了类似的A类,B类的a,b,c方法,执行单元测试,果然,错误复现。
    事故原因
    A类在执行update操作时持有x表的锁,此时A类的事务未提交。
    A类a方法执行完update操作之后,调用A类 private方法b,方法b调用B类方法c,方法c创建了新的事务
    B类方法c创建新的事务,想要对x表操作,就要获取x表的数据库锁,但是在A类paivate方法b中执行了Future.get操作,导致主线程阻塞,A类a方法的事务无法提交,由于a方法无法提交事务释放x表的锁,导致线程池的子线程无法获取x表的锁,因此双方进入了互相等待的局面。。。
    事故还原
    为了印证上面的事故原因,我分别对a,c方法加@Transactional标签以及分别执行Future.get操作,得到以下结果:


    总结
    由表格的结果可以看出,当a方法标注事务管理并b方法执行Future.get操作,会导致死锁问题。原因是a方法由于阻塞无法提交事务,就无法释放锁,而线程池的子线程(独立的事务)需要获取数据库锁才能继续执行,因此,导致了最终死锁的问题

    相关文章

      网友评论

          本文标题:记一次由@Transactional+线程池+Future共同引

          本文链接:https://www.haomeiwen.com/subject/gtinqqtx.html