死锁:Cause:com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:Deadlock found when tryin

死锁了怎么办?

  • 1、报错代码
  • 2、报错原因
  • 3、分析
      • 3.1、查询日志
      • 3.2、查询代码出处
      • 3.3、了解死锁的原因
      • 3.4、分析自己业务
  • 4、解决方案
      • 4.1、先查
      • 4.2、再改

1、报错代码

2023-02-21 10:00:05.799|ERROR|57ee46f6d2fe4109b7bb31ce0b88ef20|http-nio-9999-exec-45|com.dollycat.standard.response.CommunicationResponse|29|processException|运行时异常
org.springframework.dao.DeadlockLoserDataAccessException: 
### Error updating database.  Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: update pr_temp_remain_daily_count set `count` = `count` - 1 where activity_id = ? and `count` > 0 and date = DATE_FORMAT( NOW(), '%Y-%m-%d' )
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
; ]; Deadlock found when trying to get lock; try restarting transaction; nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
	at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:266)
	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.$Proxy82.update(Unknown Source)
	at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:294)
	at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:63)
	at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:59)
	at com.sun.proxy.$Proxy116.receiveTaskByActivityId(Unknown Source)
	at com.dollycat.system.service.impl.PrPraiseTaskServiceImpl.receiveTaskByNumberId(PrPraiseTaskServiceImpl.java:1227)
	at com.dollycat.system.service.impl.PrPraiseTaskServiceImpl$$FastClassBySpringCGLIB$$5c0424a3.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:746)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:688)
	at com.dollycat.system.service.impl.PrPraiseTaskServiceImpl$$EnhancerBySpringCGLIB$$28de655b.receiveTaskByNumberId(<generated>)
	at com.dollycat.system.controller.api.MerchantTaskController.receiveTask(MerchantTaskController.java:110)
	at sun.reflect.GeneratedMethodAccessor1356.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)

2、报错原因

死锁:Cause:com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:Deadlock found when tryin_第1张图片

3、分析

由报错原因可以看出来,报错非常的明确了哈,定位到这里是修改业务上一个订单的余量。
当时遇到这个挺头疼的,网上一搜全是一堆理论解决,当然是没问题的,但一开始不太熟悉的话会不明白那四个特性怎么去解决,怎么定位到自己的代码是为何出现了问题。
我分析一下我的定位过程:

3.1、查询日志

项目中重要的业务一定要记得打日志呀兄弟们!!!!!!虽然死锁这里它报错很明确,但是有些问题你不打日志根本排查不到的,那时候就头疼了。闲话少说,查日志便发现了上面贴出来的错误日志。
然后死锁还可以直接去数据库执行代码:SHOW ENGINE INNODB STATUS;因为Mysql会记录最后一次死锁的sql,直接执行这条语句也能快速定位到出问题的地方。

3.2、查询代码出处

根据报错行数和sql定位到了是一处update出了问题,这个update的作用是去修改活动的单量,可以理解为就是修改库存。

3.3、了解死锁的原因

我不讲那些太理论的东西,如果想知道死锁很理论的东西可以搜索一下死锁原因。原因就是你不用怀疑,必定是一个sql执行的时候将另一条需要操作的数据给锁住了,然后导致了死锁。

3.4、分析自己业务

分析一下自己哪里的业务还操作了活动单量。我这里贴出一下我还有操作到活动单量的地方(是单量的回赠,理解为退货了,库存需要又加回去)。
在这里插入图片描述

在这里插入图片描述
通过上述两条sql的分析,可以发现由延时队列发起的订单过期,库存需要回赠的时候,被前面那条领取活动的sql给锁住了,我称之为区间锁哈哈哈。

4、解决方案

经过上述的步骤,我定位到了问题所在,解决那就好办了,回到前面其他文章一直强调如何解决死锁的理论,解决方案也很简单,就是先查再改,用id去做where条件,避免条件重叠。

4.1、先查

死锁:Cause:com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:Deadlock found when tryin_第2张图片

4.2、再改

在这里插入图片描述

你可能感兴趣的:(bug,mysql,mysql,mybatis,java)