当前位置: 首页 > article >正文

Lock wait timeout exceeded; try restarting transaction

问题情况记录

记录一个曾经遇到的 MySQL 问题——锁等待超时,具体报错日志信息如下:

org.springframework.dao.CannotAcquireLockException: 
### Error updating database.  Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
### The error may exist in com/analysis/service/mapper/AnalysisLogMapper.java (best guess)
### The error may involve com.analysis.service.mapper.AnalysisLogMapper.insert-Inline
### The error occurred while setting parameters
### SQL: INSERT INTO analysis_log  ( sub_registration_no, init_sub_registration_no, task_id, type, property_description,      create_name, create_by, update_by,   auth_client, auth_client_name, registration_date, registration_expiration_date, pawnee_name_list_str, registration_type_name, form_writer,  reg_proof_file_url )  VALUES  ( ?, ?, ?, ?, ?,      ?, ?, ?,   ?, ?, ?, ?, ?, ?, ?,  ? )
### Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
; ]; Lock wait timeout exceeded; try restarting transaction; nested exception is com.mysql.cj.jdbc.exceptions.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:88)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:440)
	at com.sun.proxy.$Proxy142.insert(Unknown Source)
	at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:271)
	at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:60)
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:96)
	at com.sun.proxy.$Proxy156.insert(Unknown Source)
	at com.lls.beefeather.zhongdeng.service.mq.RpaMqReceive.saveToAiTable(RpaMqReceive.java:283)
	at com.lls.beefeather.zhongdeng.service.mq.RpaMqReceive.receiveMessage(RpaMqReceive.java:218)
	at sun.reflect.GeneratedMethodAccessor839.invoke(Unknown Source)
	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:181)
	at org.springframework.messaging.handler.invocation.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:114)
	at org.springframework.amqp.rabbit.listener.adapter.HandlerAdapter.invoke(HandlerAdapter.java:51)
	at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.invokeHandler(MessagingMessageListenerAdapter.java:182)
	at org.springframework.amqp.rabbit.listener.adapter.MessagingMessageListenerAdapter.onMessage(MessagingMessageListenerAdapter.java:120)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.doInvokeListener(AbstractMessageListenerContainer.java:1414)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.actualInvokeListener(AbstractMessageListenerContainer.java:1337)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.invokeListener(AbstractMessageListenerContainer.java:1324)
	at org.springframework.amqp.rabbit.listener.AbstractMessageListenerContainer.executeListener(AbstractMessageListenerContainer.java:1303)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.doReceiveAndExecute(SimpleMessageListenerContainer.java:817)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.receiveAndExecute(SimpleMessageListenerContainer.java:801)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer.access$700(SimpleMessageListenerContainer.java:77)
	at org.springframework.amqp.rabbit.listener.SimpleMessageListenerContainer$AsyncMessageProcessingConsumer.run(SimpleMessageListenerContainer.java:1042)
	at java.lang.Thread.run(Thread.java:748)
Caused by: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; 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 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.FilterAdapter.preparedStatement_execute(FilterAdapter.java:1081)
	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 sun.reflect.GeneratedMethodAccessor355.invoke(Unknown Source)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:498)
	at org.apache.ibatis.logging.jdbc.PreparedStatementLogger.invoke(PreparedStatementLogger.java:59)
	at com.sun.proxy.$Proxy210.execute(Unknown Source)
	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.GeneratedMethodAccessor417.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.$Proxy208.update(Unknown Source)
	at com.baomidou.mybatisplus.core.executor.MybatisSimpleExecutor.doUpdate(MybatisSimpleExecutor.java:54)
	at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
	at com.baomidou.mybatisplus.core.executor.MybatisCachingExecutor.update(MybatisCachingExecutor.java:83)
	at sun.reflect.GeneratedMethodAccessor416.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.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor.intercept(OptimisticLockerInterceptor.java:69)
	at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61)
	at com.sun.proxy.$Proxy207.update(Unknown Source)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:197)
	at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:184)
	at sun.reflect.GeneratedMethodAccessor419.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)
	... 24 common frames omitted

产生场景分析

在业务逻辑复杂的情况下,稍不留神,那么这个问题产生的概率还是挺大的。一般来说,这种问题的出现,往往都是和更新数据库表、事务、锁等相关。下面列举一下大概出现的场景:

  • 在方法上用了事务注解 @Transaction ,然后该方法里面有先后插入、更新数据库表等操作
  • 在事务里,一次性大批量更新数据,导致其它任务陷入等待,最终超时
  • 事务和锁的使用顺序不对,导致超时
  • 高并发的情况下,事务处理出现死锁,导致后面逻辑处理超时,抛出异常

不用的业务,出现的形式可能有差别,更具体的情况,需要根据实际情况分析了。

问题解决方式

  1. 调整数据库超时时间,由50s调整至120s
  2. 将代码中的大事务拆分成小事物处理,如果当前操作没有事务要求,可以考虑去掉事务
  3. 将操作表的代码块,抽离出来,引入MQ,采用异步消息处理
  4. 添加数据库表的索引
  5. 如果业务代码中是通过for循环更新或插入表记录的,调整为批量更新或批量插入

http://www.kler.cn/a/7348.html

相关文章:

  • Android OpenGL ES详解——实例化
  • linux笔记(防火墙)
  • git简介和本地仓库创建,并提交修改。git config init status add commit
  • 2024-11-16-机器学习方法:无监督学习(1) 聚类(上)
  • 2024山西省网络建设运维第十八届职业院校技能大赛解析答案(5. nginx 和 tomcat 服务)
  • GEE下载ERA5-Land气象数据(1950-至今,降水、温度)
  • 现代前端开发者的自我迷失,你还会前端基础知识吗?
  • 面向对象编程(基础)10:类的成员之三:构造器(Constructor)
  • Android Binder小结
  • 【蓝桥杯算法模板题--蓝桥题库Java】
  • 技术宅小伙:ChatGPT的编程能力到底有多厉害?
  • React 面向组件编程(下)
  • leetcode剑指 Offer 11. 旋转数组的最小数字
  • 【PR】字幕处理
  • 双指针巧解链表有环问题
  • 算法设计-hw2
  • 晶振02——晶振不能放置在PCB边缘
  • windows搭建ftp及原理(小白向)
  • 国内怎么玩chatGPT中文版-国内怎么玩chatGPT4
  • C# | 上位机开发新手指南(七)加密算法
  • 【Hello Linux】线程控制
  • springboot 统一日志
  • 百度云【人脸识别】
  • 信息论小课堂:通信趋势(万物互联)
  • Rhinoceros 7 (三维建模软件犀牛7)图文安装教程
  • 使用Docker创建一个WebSphere服务