MySQL更新死锁问题【转,纯为学习】
https://blog.csdn.net/a12345555555/article/details/72828366
-08-13 15:12:44 [ERROR] com.zhubajie.coupon.app.CouponReceiveAppServiceImpl {CouponReceiveAppServiceImpl.java:50} - ### Error updating
database. Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException:
Deadlock found when trying to get lock; try restarting transaction ### The error may involve defaultParameterMap
### The error occurred while setting parameters ### SQL: UPDATE cpn_core_coupon SET coup_num_usr = coup_num_usr + 1 WHERE coup_usr = ? AND spec_id = ? AND coup_num_usr < ?
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction ; SQL []; Deadlock found when trying to get lock; try restarting transaction;
nested exception is com.mysql.jdbc.exceptions.jdbc4.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
错误中提示下面这条sql发生了死锁
UPDATE coupon SET coup_num_usr = coup_num_usr +
1 WHERE coup_usr = ? AND spec_id = ? AND coup_num_usr < ?
首先我们来看下coupon的表结构
CREATE TABLE
`coupon` (
`id`
int(11)
NOT NULL AUTO_INCREMENT COMMENT ' ',
`spec_id`
char(20)
NOT NULL COMMENT '优惠券活动编号',
`coup_usr`
char(11)
DEFAULT NULL COMMENT '优惠券用户',
`coup_num_usr`
int(11)
unsigned NOT NULL DEFAULT
'0' COMMENT
'该用户已领取该活动的券数量', PRIMARY KEY (`id`),
KEY `coup_usr_idx` (`coup_usr`),
KEY `spec_idx` (`spec_id`))
ENGINE=InnoDB AUTO_INCREMENT=8508
DEFAULT CHARSET=utf8 COMMENT='优惠券';
其中coup usr和spec id是索引,
mysql的事务支持与存储引擎有关,MyISAM不支持事务,INNODB支持事务,更新时采用的是行级锁。这里采用的是INNODB做存储引擎,意味着会将update语句做为一个事务来处理。前面提到行级锁必须建立在索引的基础,这条更新语句用到了索引,所以这里肯定会加上行级锁。
行级锁并不是直接锁记录,而是锁索引,如果一条SQL语句用到了主键索引,mysql会锁住主键索引;如果一条语句操作了非主键索引,mysql会先锁住非主键索引,再锁定主键索引。 这个update语句会执行以下步骤: 1、由于用到了非主键索引,首先需要获取普通索引上的行级锁 2、紧接着根据主键进行更新,所以需要获取主键上的行级锁; 3、更新完毕后,提交,并释放所有锁。
如果在步骤1和2之间突然插入一条语句:UPDATE coupon SET coup num usr
= coup num usr + 1 WHERE coup usr = ? AND specid
= ? AND coup num usr < ?
就会发生死锁的情况,因为一条语句获取了普通索引的锁,等待主键锁,另外一条语句获取了主键锁,等待非主键索引,这样就出现了死锁.
如何来解决update ... where ...语句的死锁问题呢?我们可以对其进行分离,首先利用where条件找到主键,然后再利用这些主键去更新数据。
因为select * where ...语句是没有锁的,所以不存在会锁上where条件里面的字段,也就不会发生死锁的情况,只有在update的时候回锁上主键。
所以改成下面两条语句
SELECT id WHERE coup_usr = ? AND spec_id = ?UPDATE coupon SET coup_num_usr = coup_num_usr +
1 WHERE id = ? AND coup_num_usr < ?
第一条语句找出所有需要更新行的主键id,然后再一条一条更新。
在采用INNODB的MySQL中,更新操作默认会加行级锁,行级锁是基于索引的,在分析死锁之前需要查询一下mysql的执行计划,看看是否用到了索引,用到了哪个索引,对于没有用索引的操作会采用表级锁。如果操作用到了主键索引会先在主键索引上加锁,然后在其他索引上加锁,否则加锁顺序相反。在并发度高的应用中,批量更新一定要带上记录的主键,优先获取主键上的锁,这样可以减少死锁的发生。
我在项目中遇到的问题:
1.在更新设备时,使用了批量更新。
解决办法:不要使用批量更新,通过循环的方式一个一个的更新,条件要使用唯一主键uuid
2.更新断网记录时,使用了批量更新,并且条件不是唯一主键
解决办法:不要使用批量更新,查询出断网记录表的每一条数据的主键uuid,使用唯一主键uuid作为更新条件,循环的方式一个一个进行更新。
MySQL更新死锁问题【转,纯为学习】的更多相关文章
- MySQL更新死锁问题
作为一个社交类的 App ,我们有很多操作都会同时发生,为了确保数据的一致性,会采用数据库的事物. 比如现在我们有一个点赞操作,点赞成功后,需要更改文章的热度.以下是 SQL 语句: INSERT I ...
- MySql 更新死锁问题 Deadlock found when trying to get lock; try restarting transaction
文章导航-readme MySql 更新死锁问题 Deadlock found when trying to get lock; try restarting transaction 1.场景 //t ...
- MySQL更新数据时,日志(redo log、binlog)执行流程
1:背景 项目需要做Es和数据库的同步,而手动在代码中进行数据同步又是Es的一些不必要的数据同步操作和业务逻辑耦合,所以使用的了读取mysql的binlog日志的方式进行同步Es的数据. 问题1:根据 ...
- MySQL更新锁表超时 Lock wait timeout exceeded
背景 最近在做一个订单的钉钉审批功能,钉钉审批通过之后,订单更新审核状态,然后添加一条付款,并且更新付款状态: // 订单审批通过 @Transactional(rollbackFor = Excep ...
- mysql更新某个字符串字段的部分内容
如果现在需要Mysql更新字段重部分数据,而不是全部数据,应该采用何种方法呢?下面介绍了两种情况下Mysql更新字段中部分数据的方法,供您参考. Mysql更新字段中部分数据第一种情况: update ...
- 警惕 MySql 更新 sql 的 WHERE 从句中的 IN() 子查询时出现的性能陷阱
警惕 MySql 更新 sql 的 WHERE 从句中的 IN() 子查询时出现的性能陷阱 以下文章来源:https://blog.csdn.net/defonds/article/details/4 ...
- MySQL会发生死锁吗?
SHOW ENGINE INNODB STATUS;来查看死锁日志: SHOW PROCESSLIST;查看进程 MySQL的InnoDB引擎事务有4种隔离级别,主要是为了保证数据的一致性. Inno ...
- 热更新(一) 之Lua语法的学习
热更新 如热更新果需要更换UI显示,或者修改游戏的逻辑,这个时候,如果不使用热更新,就需要重新打包,然后让玩家重新下载(浪费流量和时间,体验不好).热更新可以在不重新下载客户端的情况下,更新游戏的内容 ...
- mysql更新日志问题
[root@localhost ~]# /etc/init.d/mysqld restart 停止 mysqld: [确定] 正在启动 mysqld: [确定] 故障:今天在维护以前数据库日志的时候, ...
随机推荐
- go-ethereum源码分析 PartII 共识算法
首先从共识引擎-Engine开始记录 Engine是一个独立于具体算法的共识引擎接口 Author(header) (common.Address, error) 返回打包header对应的区块的矿工 ...
- node-express-2-jade
1,Jade里可以省略尖括号,直接写标签名 2,标签间的嵌套关系用换行加空格来实现 3,紧接在标签名后加上.xx或#xx,就能给标签添加css类名和id,如果不写标签名默认就是div 4,标签属性写入 ...
- git 的安装与初始化
1搭建本地git服务器: 1.1安装git 对于ubuntu系统,一般自带git,可以使用git --version 查看版本号 ,或使用apt-get install git . centos上对 ...
- 白鹭wing的自动编译
1.lunch.json文件中的"preLaunchTask":"build",注释掉. 2.安装node-v6.11.2-x64.msi 3.安装tsc 命令 ...
- COM/DCOM简述
这些组件对象可以互相通讯与交互,而与它们的语言.分布及原始平台无关.COM规程包括一套标准API.一个标准的接口集以及COM用于支持分布式计算的网络协议.而DCOM模型则是一套用于分布式环境中的COM ...
- Bom简单介绍
1.什么是bom? 全称:浏览器对象模型(Browser Object Model) bom是js的一部分, 2.bom的对象,方法和方法 bom提供了主要的8大对象:Window,Screen,Lo ...
- SASS学习笔记!(持续学习中..)
工具 : koala 学习网址 : http://www.w3cplus.com/sassguide/syntax.html http://sass-lang.com/documentation/ ...
- open还是codecs.open区别
>>> fr = open('test.txt','a')>>> line1 = "我是一道光">>> fr.write(li ...
- Vue源码之----为什么Vue中Array的pop,push等方法可以reactive,而Array[0]='a'这样的方法不会reactive?
这就要从reactive开始讲起了,粗略的说,js的操作能引起页面上显示的改变,是因为该操作引起了组件的重新渲染,渲染会生成新的虚拟节点,新节点和旧节点会对比,操作浏览器的node进行改变. vue实 ...
- echarts设置option中的数据对象优化
if(tab.name == 'first'){ myChart.setOption({ legend: { selected:{ [this.playNumber]:true, [this.cove ...