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 ...
随机推荐
- IOI2020 国家集训队作业 泛做
题号 题目名称 rating 算法 完成情况 CF504E Misha and LCP on Tree CF505E Mr.Kitayuta vs. Bamboos CF506E Mr.Kitayut ...
- Navicat 连接 MySQL
目录 简述 新建连接 常见错误 简述 Navicat 是一套快速.可靠和全面的数据库管理工具,专门用于简化数据库管理和降低管理成本.Navicat 图形界面直观,提供简便的管理方法,设计和操作 MyS ...
- Colab教程(超级详细版)及Colab Pro/Colab Pro+使用评测
在下半年选修了机器学习的关键课程Machine learning and deep learning,但由于Macbook Pro显卡不支持cuda,因此无法使用GPU来训练网络.教授推荐使用Goog ...
- 6000字Locust入门详解
目录 一.Locust 性能测试 (一). 性能测试工具 主流性能测试工具对比 认识Locust (二) locust 基本用法 1.安装locust 2.编写用例 3. 启动测试 GUI 模式启动 ...
- FICO 常用事务码
1.SAP配置流程 1.定义,定义组织,概念,比如FI中定义公司代码,会计科目表,年度变式.SAP中有大量的定义过程. 2.分配,把会计科目表/公司/年度变式等参数分配到公司代码,逻辑组织,基本实现框 ...
- Mysql事物锁等待超时(Lock wait timeout exceeded; try restarting transaction)
一.问题描述 在做查询语句时,MySQL 抛出了这样的异常:锁等待超时 Lock wait timeout exceeded; try restarting transaction,是当前事务在等待其 ...
- Spring框架系列(9) - Spring AOP实现原理详解之AOP切面的实现
前文,我们分析了Spring IOC的初始化过程和Bean的生命周期等,而Spring AOP也是基于IOC的Bean加载来实现的.本文主要介绍Spring AOP原理解析的切面实现过程(将切面类的所 ...
- NC19916 [CQOI2010]扑克牌
NC19916 [CQOI2010]扑克牌 题目 题目描述 你有n种牌,第i种牌的数目为 \(c_i\) .另外有一种特殊的牌:joker,它的数目是m.你可以用每种牌各一张来组成一套牌,也可以用一张 ...
- PTA(BasicLevel)-1018 锤子剪刀布
一.问题定义 大家应该都会玩"锤子剪刀布"的游戏:两人同时给出手势,胜负规则如下: 剪刀 > 布, 锤子 > 剪刀, 布 > 锤子 现给出两人的交 ...
- MicTR01 Tester 开发套件(振弦采集读数仪)使用说明
MicTR01 是系列振弦模块 VM5/6/7和电子标签读写模块 TR01 开发测试.开发套件.使用 STC8 位 51 单片机为核心部件,演示上述各个型号模块的基本用法,包括了模块使用时的硬件连接和 ...