批量修改:update inner join导致死锁
问题sql:
update i_r_cmd t10 inner join ( select t10.tenant_id, t10.r_cmd_code, sum(case when t10.`report_status`=10 then 1 else 0 end) as reportSuccessCount, sum(case when t10.`report_status`=20 then 1 else 0 end) as reportFailCount from i_r_cmd_device as t10 where t10.tenant_id=? and t10.r_cmd_code=? ) as t11 on t10.tenant_id=t11.tenant_id and t10.code=t11.r_cmd_code set t10.report_success_count=t11.reportSuccessCount, t10.report_fail_count=t11.reportFailCount where t10.tenant_id=? and t10.code=?
异常信息:
2021-12-21 19:05:29,119 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1-1][TraceId:] ERROR KAFKA_CONSUMER.LOG - [处理异常: ### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction ### The error may exist in com/by/px/ipl/domain/dao/RCmdDao.java (best guess) ### The error may involve com..px.ipl.domain.dao.RCmdDao.updateReportSuccessFailCount-Inline ### The error occurred while setting parameters ### SQL: update i_r_cmd t10 inner join ( select t10.tenant_id, t10.r_cmd_code, sum(case when t10.`report_status`=10 then 1 else 0 end) as reportSuccessCount, sum(case when t10.`report_status`=20 then 1 else 0 end) as reportFailCount from i_r_cmd_device as t10 where t10.tenant_id=? and t10.r_cmd_code=? ) as t11 on t10.tenant_id=t11.tenant_id and t10.code=t11.r_cmd_code set t10.report_success_count=t11.reportSuccessCount, t10.report_fail_count=t11.reportFailCount where t10.tenant_id=? and t10.code=? ### Cause: com.mysql.cj.jdbc.exceptions.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.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction] org.springframework.dao.DeadlockLoserDataAccessException: ### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction ### The error may exist in com/by/px/ipl/domain/dao/RCmdDao.java (best guess) ### The error may involve com.by.px.ipl.domain.dao.RCmdDao.updateReportSuccessFailCount-Inline ### The error occurred while setting parameters ### SQL: update i_r_cmd t10 inner join ( select t10.tenant_id, t10.r_cmd_code, sum(case when t10.`report_status`=10 then 1 else 0 end) as reportSuccessCount, sum(case when t10.`report_status`=20 then 1 else 0 end) as reportFailCount from i_r_cmd_device as t10 where t10.tenant_id=? and t10.r_cmd_code=? ) as t11 on t10.tenant_id=t11.tenant_id and t10.code=t11.r_cmd_code set t10.report_success_count=t11.reportSuccessCount, t10.report_fail_count=t11.reportFailCount where t10.tenant_id=? and t10.code=? ### Cause: com.mysql.cj.jdbc.exceptions.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.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:271) at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72) at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:88) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:440) at com.sun.proxy.$Proxy161.update(Unknown Source) at org.mybatis.spring.SqlSessionTemplate.update(SqlSessionTemplate.java:287) at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:65) at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:96) at com.sun.proxy.$Proxy196.updateReportSuccessFailCount(Unknown Source) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:344) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:198) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at com.by.px.mountain.core.common.aop.PerformanceInstrumentInterceptor.invoke(PerformanceInstrumentInterceptor.java:30) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy197.updateReportSuccessFailCount(Unknown Source) at com.by.px.ipl.domain.repository.rCmdDomainRepository.updateReportSuccessFailCount(rCmdDomainRepository.java:200) at com.by.px.ipl.domain.repository.rCmdDomainRepository$$FastClassBySpringCGLIB$$5967492e.invoke(<generated>) at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:771) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at com.by.px.mountain.core.common.aop.PerformanceInstrumentInterceptor.invoke(PerformanceInstrumentInterceptor.java:30) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:749) at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:691) at com.by.px.ipl.domain.repository.rCmdDomainRepository$$EnhancerBySpringCGLIB$$b6cfb8d1.updateReportSuccessFailCount(<generated>) at com.by.px.ipl.domain.partial.report.action.cmd.rCmdReportLogAction.doAction(rCmdReportLogAction.java:74) at com.by.px.ipl.domain.partial.report.ReportDispatcherDomain.executeAction(ReportDispatcherDomain.java:91) at com.by.px.mountain.core.common.service.seviceTemplateImpl$1.doInTransaction(seviceTemplateImpl.java:49) at com.by.px.mountain.core.common.service.seviceTemplateImpl$1.doInTransaction(seviceTemplateImpl.java:46) at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:140) at com.by.px.mountain.core.common.service.seviceTemplateImpl.execute(seviceTemplateImpl.java:45) at com.by.px.ipl.domain.partial.report.ReportFactory.dispatcher(ReportFactory.java:41) at com.by.px.ipl.domain.kafka.KafkaConsumer.listen(KafkaConsumer.java:53) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:171) at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:120) at org.springframework.kafka.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:48) at org.springframework.kafka.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:329) at org.springframework.kafka.listener.adapter.BatchMessagingMessageListenerAdapter.invoke(BatchMessagingMessageListenerAdapter.java:170) at org.springframework.kafka.listener.adapter.BatchMessagingMessageListenerAdapter.onMessage(BatchMessagingMessageListenerAdapter.java:162) at org.springframework.kafka.listener.adapter.BatchMessagingMessageListenerAdapter.onMessage(BatchMessagingMessageListenerAdapter.java:58) at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeBatchOnMessage(KafkaMessageListenerContainer.java:1702) at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeBatchOnMessageWithRecordsOrList(KafkaMessageListenerContainer.java:1693) at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeBatchOnMessage(KafkaMessageListenerContainer.java:1651) at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.doInvokeBatchListener(KafkaMessageListenerContainer.java:1586) at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeBatchListener(KafkaMessageListenerContainer.java:1479) at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.invokeListener(KafkaMessageListenerContainer.java:1462) at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.pollAndInvoke(KafkaMessageListenerContainer.java:1128) at org.springframework.kafka.listener.KafkaMessageListenerContainer$ListenerConsumer.run(KafkaMessageListenerContainer.java:1031) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) at java.util.concurrent.FutureTask.run(FutureTask.java:266) at java.lang.Thread.run(Thread.java:748) Caused by: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:121) at com.mysql.cj.jdbc.exceptions.SQLError.createSQLException(SQLError.java:95) at com.mysql.cj.jdbc.exceptions.SQLExceptionsMapping.translateException(SQLExceptionsMapping.java:122) at com.mysql.cj.jdbc.ClientPreparedStatement.executeInternal(ClientPreparedStatement.java:960) at com.mysql.cj.jdbc.ClientPreparedStatement.execute(ClientPreparedStatement.java:388) at sun.reflect.GeneratedMethodAccessor247.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.mysql.cj.jdbc.ha.MultiHostConnectionProxy$JdbcInterfaceProxy.invoke(MultiHostConnectionProxy.java:105) at com.sun.proxy.$Proxy318.execute(Unknown Source) at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute(FilterChainImpl.java:3461) at com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_execute(FilterEventAdapter.java:440) at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute(FilterChainImpl.java:3459) at com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_execute(FilterEventAdapter.java:440) at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute(FilterChainImpl.java:3459) at com.alibaba.druid.filter.FilterEventAdapter.preparedStatement_execute(FilterEventAdapter.java:440) at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute(FilterChainImpl.java:3459) at com.alibaba.druid.proxy.jdbc.PreparedStatementProxyImpl.execute(PreparedStatementProxyImpl.java:167) at com.alibaba.druid.pool.DruidPooledPreparedStatement.execute(DruidPooledPreparedStatement.java:497) at org.apache.ibatis.executor.statement.PreparedStatementHandler.update(PreparedStatementHandler.java:47) at org.apache.ibatis.executor.statement.RoutingStatementHandler.update(RoutingStatementHandler.java:74) at sun.reflect.GeneratedMethodAccessor232.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:49) at com.by.px.ipl.web.interceptor.MybatisSqlLogInterceptor.intercept(MybatisSqlLogInterceptor.java:65) at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61) at com.sun.proxy.$Proxy317.update(Unknown Source) at sun.reflect.GeneratedMethodAccessor232.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:63) at com.sun.proxy.$Proxy317.update(Unknown Source) at sun.reflect.GeneratedMethodAccessor232.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:63) at com.sun.proxy.$Proxy317.update(Unknown Source) at sun.reflect.GeneratedMethodAccessor232.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:49) at com.by.px.ipl.web.interceptor.MybatisSqlLogInterceptor.intercept(MybatisSqlLogInterceptor.java:65) at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61) at com.sun.proxy.$Proxy317.update(Unknown Source) at com.baomidou.mybatisplus.core.executor.MybatisReuseExecutor.doUpdate(MybatisReuseExecutor.java:55) at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117) at sun.reflect.GeneratedMethodAccessor411.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:63) at com.sun.proxy.$Proxy316.update(Unknown Source) at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:197) at sun.reflect.GeneratedMethodAccessor359.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:426) ... 60 common frames omitted 2021-12-21 19:05:29,124 [org.springframework.kafka.KafkaListenerEndpointContainer#0-0-C-1-1][TraceId:] INFO KAFKA_CONSUMER.LOG - [seviceTemplate.execute(...)
解决方案:
拆解为单个sql去修改,去掉inner join update。
update join会导致锁表。
基础才是编程人员应该深入研究的问题,比如:
1)List/Set/Map内部组成原理|区别
2)mysql索引存储结构&如何调优/b-tree特点、计算复杂度及影响复杂度的因素。。。
3)JVM运行组成与原理及调优
4)Java类加载器运行原理
5)Java中GC过程原理|使用的回收算法原理
6)Redis中hash一致性实现及与hash其他区别
7)Java多线程、线程池开发、管理Lock与Synchroined区别
8)Spring IOC/AOP 原理;加载过程的。。。
【+加关注】。