mvn -test 导致事务死锁

Posted by 孙继峰 on May 30, 2020

起因

写完测试类之后, Junit 跑通了全部的测试类, 在执行 mvn test 的时候执行了有10分钟, 然后有几个测试类失败了, 都是由于事务超时关闭, 我就觉得很奇怪, 为什么 Junit 跑没问题, 而用 Maven 跑就会出问题呢?


报错信息

Error flushing statements.  
Cause: 
    org.apache.ibatis.executor.BatchExecutorException:
      com.xxxx.service.goodscenter.mapper.GoodsInfoMapper.updateById (batch index #1) failed. 
Cause: 
    java.sql.BatchUpdateException: 
        Lock wait timeout exceeded; try restarting transaction 

看错误原因可知道是加锁超时了


分析原因

在这里使用”5个为什么”的方式来进行分析原因

  • 为什么 mvn 构建失败? 因为 mvn test 执行失败
  • 为什么 mvn test 执行失败? 因为有测试用例没有通过测试
  • 为什么 测试用例没有通过测试? 因为加锁超时了
  • 为什么加锁超时了? 不太清楚… 开始解决最后一个为什么 —

搜集信息

mysql > SHOW FULL PROCESSLIST; |commond|time|state|info| |———-|—-|——|—-| |Query|39|updating|UPDATE goods_info SET show_status=0, WHERE id=767338| mysql > SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS; |lock_id |lock_trx_id |lock_mode |lock_type |lock_table |lock_index |lock_space |lock_page |lock_rec |lock_data| |-|-|-|-|-|-|-|-|-|-| |391193218:1446:87822:21 |391193218 |X |RECORD |goods_info |PRIMARY |1446 |87822 |21 |767338| |391193172:1446:87822:21 |391193172 |X |RECORD |goods_info |PRIMARY |1446 |87822 |21 |767338| 发现问题了, 两个事务占了同一行数据!


继续分析原因

  • 为什么 mvn 构建失败? 因为 mvn test 执行失败
  • 为什么 mvn test 执行失败? 因为有测试用例没有通过测试
  • 为什么 测试用例没有通过测试? 因为加锁超时了
  • 为什么加锁超时了? 因为两个事务占了同一条数据
  • 为什么两个事物占了同一条数据?

    继续搜集信息

    程序中我一定没写过并发相关测试用例, 在死锁过程中我dump了一下当前线程 发现有多个线程跑测试用例

根本原因

然后问题就来到了我的测试用例, 在数据库集成测试的时候我会批量保存并更新一些数据, 保存时商品的唯一索引(gid)是我写死在程序中的, 间接导致死锁的.
这个解释有些不足, 因为我个人还没太理解, 但是对于MySQL的认知还不足, 只能止步于此了, 以后一定系统的学习一下MySQL