起因
写完测试类之后, 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