MySQL批量更新死锁案例分析

【物联网】基于LORA组网的远程环境监测系统设计(ThingsCloud云平台版)_资料编号34 实现一主多从的LORA组网远程通信,主机和两个从机都配备了STM32F103单片机与 LoRa 模块,主机作为中心设备及WIFI网关,负责接收和发送数据到远程物联网平台和手机APP,两个从机则负责采集数据并通过各自的 LoRa组网将数据发送给主机。 阅读详情

问题描述
在做项目的过程中,由于写SQL太过随意,一不小心就抛了一个死锁异常,如下:

com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction  
        at sun.reflect.GeneratedConstructorAccessor247.newInstance(Unknown Source)  
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)  
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)  
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)  
        at com.mysql.jdbc.Util.getInstance(Util.java:381)  
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1045)  
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)  
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3491)  
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3423)  
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1936)  
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2060)  
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2542)  
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1734)  
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:2019)  
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1937)  
        at com.mysql.jdbc.PreparedStatement.executeUpdate(PreparedStatement.java:1922)  

表结构如下:

CREATE TABLE `user_item` (  
  `id` BIGINT(20) NOT NULL,  
  `user_id` BIGINT(20) NOT NULL,  
  `item_id` BIGINT(20) NOT NULL,  
  `status` TINYINT(4) NOT NULL,  
  PRIMARY KEY (`id`),  
  KEY `idx_1` (`user_id`,`item_id`,`status`)  
) ENGINE=INNODB DEFAULT CHARSET=utf-8  

SQL语句如下:

update user_item set status=1 where user_id=? and item_id=?  

原因分析
MySQL的事务支持与存储引擎有关,MyISAM不支持事务,INNODB支持事务,更新时采用的是行级锁。这里采用的是INNODB做存储引擎,意味着会将update语句做为一个事务来处理。前面提到行级锁必须建立在索引的基础,这条更新语句用到了索引idx_1,所以这里肯定会加上行级锁。
行级锁并不是直接锁记录,而是锁索引,如果一条SQL语句用到了主键索引,mysql会锁住主键索引;如果一条语句操作了非主键索引,mysql会先锁住非主键索引,再锁定主键索引。
这个update语句会执行以下步骤:
1、由于用到了非主键索引,首先需要获取idx_1上的行级锁
2、紧接着根据主键进行更新,所以需要获取主键上的行级锁;
3、更新完毕后,提交,并释放所有锁。
如果在步骤1和2之间突然插入一条语句:update user_item …..where id=? and user_id=?,这条语句会先锁住主键索引,然后锁住idx_1。
蛋疼的情况出现了,一条语句获取了idx_1上的锁,等待主键索引上的锁;另一条语句获取了主键上的锁,等待idx_1上的锁,这样就出现了死锁。
解决方案
1、先获取需要更新的记录的主键

select id from user_item where user_id=? and item_id=?  

2、逐条更新

for (Long id : idList) {  
    userItemDAO.updateStatus(id, userId, 1);  
}  
update user_item set status=? where id=? and user_id=?

这样貌似解决了,都是对单条进行操作,都是先获取主键上的锁,再获取idx_1上的锁。
不过这个解决方案与先前的更新语句不一样,先前的更新语句对所有记录的更新在一个事务中,采用循环更新后并不在同一个事务中,所以在for循环外面还得开一个事务。




Exception e = (Exception)getDbfeelTransactionTemplate().execute(new TransactionCallback() {  
   public Object doInTransaction(TransactionStatus status) {  
      try {  
            for(Long id:idList) {  
        <span style="white-space:pre">  </span>userItemDAO.updateStatus(id,userId,1)  
        }  
            return null;  
      }catch(DAOException e) {  
         status.setRollbackOnly();  
         return e;  
      }  
      catch (Exception e) {  
         status.setRollbackOnly();  
         return e;  
      }  
   }  
});  

小结:在采用INNODB的MySQL中,更新操作默认会加行级锁,行级锁是基于索引的,在分析死锁之前需要查询一下mysql的执行计划,看看是否用到了索引,用到了哪个索引,对于没有用索引的操作会采用表级锁。如果操作用到了主键索引会先在主键索引上加锁,然后在其他索引上加锁,否则加锁顺序相反。在并发度高的应用中,批量更新一定要带上记录的主键,优先获取主键上的锁,这样可以减少死锁的发生。

visio安装包 Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。 立即下载

相关推荐

IEC103协议实战指南:报文解析与传输优化策略

本文深入解析IEC103协议在电力自动化系统中的核心应用,重点拆解其固定帧与可变帧两种报文格式,并详细阐述了主从问答与非平衡传输机制。文章结合实战经验,针对报文解析中的常见问题(如字节序、超时重发)提供了解决方案,并探讨了传输层优化策略,旨在帮助工程师实现更可靠、高效的通信链路。

r2s3t4的博客 542

【Java】Lock锁的细节内容-ORA-00060: 等待资源时检测到死锁

代码中如何正确使用Lock锁

weixin_42369773的博客 1484

Linux系统下奥比中光Astra Pro相机SDK部署与避坑指南

本文详细指导了在Linux系统下部署奥比中光Astra Pro深度相机SDK的全过程,涵盖系统准备、SDK安装、设备权限配置及常见问题排查。重点解析了USB设备规则配置这一关键步骤,并提供了Python与C++项目的集成方法,旨在帮助开发者快速完成相机配置,避免常见陷阱。

weixin_28455801的博客 300

批量更新出现死锁问题

通常使用insert、update、delete等操作的时候,数据库会进行锁表操作。需要在条件字段添加上索引条件,使表锁转换成行级锁,减少对数据的锁定。),行锁会先对非主键索引进行锁定在进行主键索引锁定。所以当更新语句操作到非主键索引时,不仅会锁行记录,还会锁住非主键索引。从而占用资源导致死锁。update语句进行不要对非主键索引进行操作,避免更多资源的锁定。Mysql出现死锁主要是有两种情况。- 第二种是,数据库出现行级锁(

weixin_49363689的博客 5548

手把手教你用STM32F103的IO口模拟XY2-100协议驱动数字振镜(附Keil O3优化代码)

本文详细介绍了如何使用STM32F103的IO口模拟XY2-100协议驱动数字振镜,包括协议解析、偶校验算法、寄存器级优化及Keil O3编译下的性能调优。通过硬件配置、核心代码实现和优化技巧,帮助开发者实现高速二维偏转控制,适用于工业激光雕刻和精密定位系统。

weixin_42527401的博客 261

SerDes系列之 SSC扩频时钟技术

扩频时钟,又称展频(SSC-Spread Spectrum Clocking),当前PCIE、DDR、USB等几乎所有的高速接口都支持SSC的功能。电子工程师在日常的电气测试中经常与之接触,在电磁传导和辐射发射验证过程中,经常需要使用到芯片的SSC功能,它的物理表现形式,就是信号的比特率会在一个很小的范围内浮动,多见于周期性变化的时钟信号。

一只豌豆象的博客 3443

记录一次线程死锁调试的过程,结果待定。。。。

记录一次线程死锁调试的过程,结果待定。。。。 现场不知道具体因为什么原因导致线程直接死掉,没有任何异常抛出,只能一步一步的调试 1、现场用的是pg数据库,发现数据库会出现锁表现象查询方法如下: --查询是否锁表了 select oid from pg_class where relname='可能锁表了的表' select pid from pg_locks where relation='上面查出的oid' --如果查询到了结果,表示该表被锁 则需要释放锁定 select pg_cancel_backen

dongyang1124的博客 344

IEC 104电力规约详细解读(一) - 报文结构、报文分类、ASDU

比如,双方可以按频率发送,比如接收8帧I帧回答一帧S帧,也可以要求接收1帧I帧就应答1帧S帧,当然也可以不要求(S帧内容示例参考例1)。所以U帧格式的控制欲第一个字节就只有6种情况,分别是0x83(TESTER确认)、0x43(TESTER命令)、0x23(STOPDT确认)、0x13(STOPDT命令)、0x0B(START确认)、0x07(START命令)ASDU(应用服务数据单元),协议原文格式最好去101协议去看看,会比较详细。遥信、遥测、遥控、遥调、总召、对时等都需要使用I格式传送。

张二狗的博客 1万+

mysql死锁异常分析及解决

前言 其实在这次之前也发生过死锁异常,但当时并没当回事,也没分析数据,简单的认为是偶发现象,并且是修改同一用户产生,于是就在最初添加了select for update,直到这两天发生了好几笔,分析数据发现并不是之前猜测的那样 问题产生 这两天老接到运维通知,说某客户又发生了卡单现象,让我分析下问题,然后找来日志,异常信息如下: ### Error updating database. Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollback

qq_37910618的博客 6574

PyTorch实战(21)——扩散模型(Diffusion Model)

扩散模型通过简单的噪声扩散过程,就能创造出高质量的超现实图像。在本节中,我们首先学习了扩散如何用于图像生成,了解了扩散模型的内部运作机制。随后基于动漫图像数据集,使用 PyTorch 和 Hugging Face 框架训练和运行自定义扩散模型,生成逼真动漫图像。

盼小辉丶的博客 3412

【Bug已解决】Claude Desktop Cowork 报错 Workspace unavailable 解决方案

方案适用场景推荐指数确认虚拟机镜像下载完整性排查的第一步,最基础的前提检查⭐⭐⭐⭐⭐确认虚拟机平台功能已启用Windows 系统功能层面的必要条件⭐⭐⭐⭐⭐重启 CoworkVMService快速尝试恢复服务正常状态⭐⭐⭐⭐完全重启客户端排除临时性状态错乱⭐⭐⭐⭐降级使用文件工具临时替代方案,不阻塞当前工作⭐⭐⭐报错的本质是Cowork 功能依赖的虚拟机管理服务,在 Windows 应用包隔离机制下未能正确定位虚拟机文件的实际存放路径。

博客 6240

mysql innodb 并发插入问题,包大量死锁错误

开了10个并发写线程,没1000条记录批量提交一次,结果mysql包大量死锁错误! "Deadlock found when trying to get lock; try restarting transaction" 引擎用的是Innodb 主键字段是auto_increament. mysql 有这么脆弱吗? create table ASIA_ODDS( id in...

u011250186的博客 1876

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

MySql批量更新死锁案例分析

http://blog.youkuaiyun.com/aesop_wubo/article/details/8286215 问题描述 在做项目的过程中,由于写SQL太过随意,一不小心就抛了一个死锁异常,如下: 表结构如下: SQL语句如下: update user_item setstatus=1 where user_id=? and item_id=? 原因分析 MySQL...

hellozhxy的博客 1099

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

mysql 批量更新 避免死锁_MySQL批量更新死锁案例分析

问题描述在做项目的过程中,由于写SQL太过随意,一不小心就抛了一个死锁异常,如下:com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:Deadlockfoundwhentryingtogetlock;tryrestartingtransactionatsun.reflect.GeneratedCo...

weixin_39721953的博客 819

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

mysql 批量更新 死锁_MySQL批量更新死锁案例分析

问题描述在做项目的过程中,由于写SQL太过随意,一不小心就抛了一个死锁异常,如下:com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:Deadlockfoundwhentryingtogetlock;tryrestartingtransactionatsun.reflect.GeneratedCo...

weixin_35733586的博客 539

mysql批量更新 死锁_[转]MySQL批量更新死锁案例分析

文章出处:http://blog.youkuaiyun.com/aesop_wubo/article/details/8286215问题描述在做项目的过程中,由于写SQL太过随意,一不小心就抛了一个死锁异常,如下:com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to ge...

weixin_28881787的博客 262

mysql 批量更新死锁_[转]MySQL批量更新死锁案例分析

文章出处:http://blog.youkuaiyun.com/aesop_wubo/article/details/8286215问题描述在做项目的过程中,由于写SQL太过随意,一不小心就抛了一个死锁异常,如下:com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to ge...

weixin_32724679的博客 139

Mysql更新text容易死锁_MySQL批量更新死锁案例分析

问题描述在做项目的过程中,由于写SQL太过随意,一不小心就抛了一个死锁异常,如下:com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:Deadlockfoundwhentryingtogetlock;tryrestartingtransactionatsun.reflect.GeneratedCo...

weixin_39920415的博客 195

mysql 批量更新 避免死锁_MySQL批量更新死锁案例分析--转载

问题描述在做项目的过程中,由于写SQL太过随意,一不小心就抛了一个死锁异常,如下:com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:Deadlockfoundwhentryingtogetlock;tryrestartingtransactionatsun.reflect.GeneratedCo...

weixin_32300981的博客 825

MySQL批量更新死锁案例分析(转载)

死锁

C18298182575的博客 1182
上一篇: j-jodatime.html
下一篇: SpringMVC 使用JSR-303进行校验 @Valid
zljjava
博客等级 码龄15年 155粉丝 15原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值