什么问题?
后台日志打印出这样的问题。 Lock wait timeout exceeded; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
什么场景?
-
页面上修改信息,Java端需要通过mq下发任务到底层C++,C++负责执行任务
-
第一次发出修改请求,底层C++未返回任何信息,后台日志没有任何日志打印
- 第二次发出修改请求,报出Lock wait timeout exceeded;
什么原因?
第一次请求事务A执行过程中,通过mq下发任务给C++端,但是没有任何信息(成功、失败)返回,导致事务A一直处于running状态。没有commit也没有rollback。
第二次请求事务B拿不到锁,因为事务A一直处于执行中,没有释放事务锁,所以事务B就等待1分钟超时了。
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
; Lock wait timeout exceeded; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:262)
at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:73)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:446)
at com.sun.proxy.$Proxy155.update(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:294)
at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:62)
at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
at com.sun.proxy.$Proxy205.updateByPrimaryKeySelective(Unknown Source)
at com.byavs.drwisas.business.dao.PetitionPersonMapper.updateByPrimaryKeySelective(PetitionPersonMapper.java:97)
at com.byavs.drwisas.business.service.PetitionPersonService.update(PetitionPersonService.java:301)
解决方法:
因为C++端没有打开联通接口,所以也不会返回任何信息、无论成功或是失败。然后Java端这边事务处理就没有commit和rollback,这样就一直占用事务锁,导致其他事务拿不到锁。
这种情况需要解决,但是mq里没有等待超时的处理,所以需要设置一个默认时间,当没有任何信息返回的时候,Java端直接抛出异常,触发事务rollback操作,同时释放事务锁
扩展
网上有很多遇到这个这个问题是因为同一时间内对同一条数据做修改和删除的操作导致的。瞬间出现高并发的现象导致的死锁,我这种情况是因为第一次请求的事务一直在running中。导致往后的请求都lock wait timeout exceeded。
***查看数据库当前的进程
mysql> show processlist;
***查看所有运行中的事务
mysql> SELECT * FROM information_schema.INNODB_TRX;
***查看当前出现的锁
mysql> SELECT * FROM information_schema.INNODB_LOCKs;
此时我们再次发起请求、查看所有运行中的事务
这时候就出现等待锁,这就是因为第一次请求的事务锁一直处于运行中,还未释放,第二次请求就只能等待了。