MySQL更新锁表超时 Lock wait timeout exceeded
背景
最近在做一个订单的钉钉审批功能,钉钉审批通过之后,订单更新审核状态,然后添加一条付款,并且更新付款状态:
// 订单审批通过
@Transactional(rollbackFor = Exception.class)
public void orderPass() {
// 更新订单审核状态
updateOrderAuditStatus(id);
// 添加入库
addPutInStorage(id);
// 更新订单入库状态
updateOrderStorageStatus(id);
}
其中的添加入库是远程ERP入库,添加出库之后更新出库状态。因为ERP可能因为库存不足,会入库失败。但此时审批流程已经结束,不可能再发起一遍审批流程。当添加入库失败时订单审核状态正常更新,添加入库和更新入库状态失败。这里的解决方案是:
拆分成两个方法,一个是更新订单审核状态,另一个添加入库和更新入库状态。添加入库和更新入库状态开启一个事务,也就是添加
嵌套事务 REQUIRES_NEW,REQUIRES_NEW表示无论是否有事务,都会创建一个新的事务。
修改后的代码如下:
// 订单审批通过
@Transactional(rollbackFor = Exception.class)
public void orderPass() {
// 更新订单审核状态
updateOrderAuditStatus(id);
try {
// 更新出库
updatePutInStorage(id);
} catch (Exception e) {
System.out.println("更新出库失败");
}
}
// 更新出库
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
public void updatePutInStorage(Long id) throws Exception{
// 添加入库
addPutInStorage(id);
// 更新订单入库状态
updateOrderStorageStatus(id);
System.out.println("更新出库成功");
}
上面讲代码拆分成更新订单审核状态和更新入库,其中更新入库报错会被try catch异常捕获,不会影响到订单审核状态更新。而添加入库和更新订单入库状态处于同一个事务下,要么同时成功,要么同时失败。上述问题也解决了。
然而运行结果:
com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
原因分析
锁超时了,为什么会有锁呢?主要是这里添加了REQUIRES_NEW。
- 外层事务对表的更新锁住了表的行,外层事务还没有提交,就调用了内层事务
updatePutInStorage,内层事务调用了updatePutInStorage。 updatePutInStorage需要更新订单的入库状态,此时外层事务锁住了该表,所以更新订单的入库状态无法更新。更新订单的入库状态等待更新订单的审核状态,而REQUIRES_NEW又会让更新订单的审核状态等待更新订单的入库状态。造成相互等待,也就造成死锁。
解决方案
死锁:两个线程为了保护两个不同的共享资源而使用了两个互斥锁,那么这两个互斥锁应用不当的时候,可能会造成两个线程都在等待对方释放锁,在没有外力的作用下,这些线程会一直相互等待,就没办法继续运行,这种情况就是发生了死锁。
上面锁超时原因,就是死锁的一种原因。所以需要把更新订单审核状态方法放在最后:
// 订单审批通过
@Transactional(rollbackFor = Exception.class)
public void orderPass() {
try {
// 更新出库
updatePutInStorage(id);
} catch (Exception e) {
System.out.println("更新出库失败");
}
// 更新订单审核状态
updateOrderAuditStatus(id);
}
// 更新出库
@Transactional(rollbackFor = Exception.class,propagation = Propagation.REQUIRES_NEW)
public void updatePutInStorage(Long id) throws Exception{
// 添加入库
addPutInStorage(id);
// 更新订单入库状态
updateOrderStorageStatus(id);
System.out.println("更新出库成功");
}
总结
- 添加嵌套事务需要考虑到
死锁的问题。 - 一个事务只有等全部方法执行完毕之后才会提交事务。
- 含有嵌套的事务的更新,需要按照相同的顺序更新,不然可能会出现锁相互等待的情况。
参考
业务上第一次遇到MySQL更新锁表超时( Lock wait timeout exceeded; try restarting transaction)
MySQL更新锁表超时 Lock wait timeout exceeded的更多相关文章
- Mysql事物锁等待超时(Lock wait timeout exceeded; try restarting transaction)
一.问题描述 在做查询语句时,MySQL 抛出了这样的异常:锁等待超时 Lock wait timeout exceeded; try restarting transaction,是当前事务在等待其 ...
- MySQL事务锁等待超时 Lock wait timeout exceeded; try restarting transaction
工作中处理定时任务分发消息时出现的问题,在查找并解决问题的时候,将相关的问题博客收集整理,在此记录下,以便之后再遇到相同的问题,方便查阅. 问题场景 问题出现的场景: 在消息队列处理消息时,同一事务内 ...
- com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction
本文为博主原创: 以下为在程序运行过程中报的错误, org.springframework.dao.CannotAcquireLockException: ### Error updating dat ...
- com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Lock wait timeout exceeded; try restarting transaction 问题解决
有两种设置方法 第一种在mysql的配置文件中加入,然后重启mysql innodb_lock_wait_timeout = 500 第二种直接执行如下命令 set global innodb_loc ...
- Mysql错误:ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction
昨晚添加完索引之后, 查询整表的时候抛出Lock wait timeout exceeded; try restarting transaction, 吓死小白的我, 为什么条件查询可以, 整表查不了 ...
- Mysql错误: ERROR 1205: Lock wait timeout exceeded解决办法(MySQL锁表、事物锁表的处理方法)
Java执行一个SQL查询未提交,遇到1205错误. java.lang.Exception: ### Error updating database. Cause: java.sql.SQLExc ...
- mysql异常Lock wait timeout exceeded; try restarting transaction
mysql中使用update语句更新数据报错: Lock wait timeout exceeded; try restarting transaction. 这是由于你要更新的表的锁在其它线程手里. ...
- Lock wait timeout exceeded?代码该优化了
背景 最近在排查问题时发现,偶尔会发生关于数据库锁超时的现象,会发生像如下的报错信息: Exception in thread "pool-3-thread-1" org.spri ...
- MySQL事务锁问题-Lock wait timeout exceeded
转载:https://cloud.tencent.com/developer/article/1356959 问题现象: 接口响应时间超长,耗时几十秒才返回错误提示,后台日志中出现Lock wai ...
随机推荐
- consul系列文章02---替换掉.netcore的配置文件
如果是开发微服务的项目,多个服务的配置管理起来比较麻烦,需要集中管理,也就是需要有配置中心: consul集成配置中心的思路:读取配置文件时不在从本地的应用中读取,而是从consul的KEY/valu ...
- vue面试总结-2022
1.vue生命周期及各周期得特点 beforCreate 特点: 初始化实例,不能使用data和methods.ref 示例 beforeCreate: function () { console.g ...
- 测试平台系列(97) 完善执行case部分
大家好~我是米洛! 我正在从0到1打造一个开源的接口测试平台, 也在编写一套与之对应的教程,希望大家多多支持. 欢迎关注我的公众号米洛的测开日记,获取最新文章教程! 回顾 上一节我们讨论了怎么结束一个 ...
- 1.Shell编程循环语句(if 、while、 until)
循环语句 for循环语句 读取不同的变量值,用来逐个执行同一组命令 格式: for 变量名 in 取值列表 do 命令序列 done 示例:批量创建用户并设置密码 [root@localhost da ...
- python基础知识-day9(数据驱动)
1.数据驱动的概念 在自动化测试中,需要把测试的数据分离到JSON,YAML等文件中. 2.YAML 的相关知识 YAML 入门教程 分类 编程技术 YAML 是 "YAML Ain't a ...
- 【WPF】CAD工程图纸转WPF可直接使用的xaml代码技巧
前言:随着工业化的进一步发展,制造业.工业自动化等多领域,都可能用到上位监控系统.而WPF在上位监控系统方面,应该算是当下最流行的前端框架之一了.而随着监控体系的不断完善与更新迭代,监控画面会变得越来 ...
- 使用vue实现排序算法演示动画
缘起 最近做的一个小需求涉及到排序,界面如下所示: 因为项目是使用vue的,所以实现方式很简单,视图部分不用管,本质上就是操作数组,代码如下: { // 上移 moveUp (i) { // 把位置i ...
- 全新升级的AOP框架Dora.Interception[6]: 框架设计和实现原理
本系列前面的五篇文章主要介绍Dora.Interception(github地址,觉得不错不妨给一颗星)的编程模式以及对它的扩展定制,现在我们来聊聊它的设计和实现原理.(拙著<ASP.NET C ...
- Python:socket编程教程
ocket是基于C/S架构的,也就是说进行socket网络编程,通常需要编写两个py文件,一个服务端,一个客户端. 首先,导入Python中的socket模块: import socket Pytho ...
- 解决方案:可以ping别人,但是别人不能ping我
背景:我在写分布式爬虫项目时遇到了slave端无法ping通我的master,我的master可以ping通slave.我将master的防火墙关闭后slave可以ping了,但是这不是解决办法.于是 ...