网站首页 > 技术教程 正文
昨晚我正在床上睡得着着的,突然来了一条短信。
啥,线上MySQL死锁了,我赶紧登录线上系统,查看业务日志。
能清楚看到是这条insert语句发生了死锁。
MySQL如果检测到两个事务发生了死锁,会回滚其中一个事务,让另一个事务执行成功。很明显,我们这条insert语句被回滚了。
insert into user (id, name, age) values (6, '张三', 6);
但是我们怎么排查这个问题呢?
到底跟哪条SQL产生了死锁?
好在MySQL记录了最近一次的死锁日志,可以用命令行工具查看:
show engine innodb status;
在死锁日志中,可以清楚地看到这两条insert语句产生了死锁,最终事务2被会回滚,事务1执行成功。
# 事务1
insert into user (id,name,age) values (5,'张三',5);
# 事务2
insert into user (id,name,age) values (6,'李四',6);
这两条insert语句,怎么看也不像能产生死锁,我们来还原一下事发过程。
先看一下对应的Java代码:
@Override
@Transactional(rollbackFor = Exception.class)
public void insertUser(User user) {
User userResult = userMapper.selectByIdForUpdate(user.getId());
// 如果userId不存在,就插入数据,否则更新
if (userResult == null) {
userMapper.insert(user);
} else {
userMapper.update(user);
}
}
业务逻辑代码很简单,如果userId不存在,就插入数据,否则更新user对象。
从死锁日志中,我们看到有两条insert语句,很明显userId=5和userId=6的数据都不存在。
所以对应的SQL执行过程,可能就是这样的:
先用for update加上排他锁,防止其他事务修改当前数据,然后再insert数据,最后发生了死锁,事务2被回滚。
两个事务分别在两个主键ID上面加锁,为什么会产生死锁呢?
如果看过上篇文章,就会明白。
当id=5存在这条数据时,MySQL就会加Record Locks(记录锁),意思就是只在id=5这一条记录上加锁。
当id=5这条记录不存在时,就会锁定一个范围。
假设表中的记录是这样的:
id | name | age |
1 | 王二 | 1 |
10 | 一灯 | 10 |
select * from user where id=5 for update;
这条select语句锁定范围就是 (1, 10]。
最后两个事务的执行过程就变成了:
通过这个示例看到,两个事务都可以先后锁定 (1, 10]这个范围,说明MySQL默认加的临键锁的范围是可以交叉的。
那怎么解决这个死锁问题呢?
我能想到的解决办法就是,把这两个语句select和insert,合并成一条语句:
insert into user (id,name,age) values (5,'张三',5)
on duplicate key update name='张三',age=5;
大家有什么好办法吗?
这个死锁情况,还是挺常见的,赶紧回去翻一下项目代码有没有这样的问题。
推荐阅读:《我爱背八股系列》
为什么要用MQ?MQ的作用有哪些?
高并发场景下,如何保证数据的一致性的?
如何进行分库分表?分库分表后有哪些问题以及对应的解决方案。
高并发下怎么生成订单ID?以及每种方案的优缺点。
如何实现分布式锁?使用数据库、分布式数据库、分布式协调服务分别如何实现?MySQL索引底层数据结构为什么要用B+树?以及红黑树、B树的优缺点。
一篇文章讲清楚MySQL的聚簇/联合/覆盖索引、回表、索引下推
ThreadLocal线上故障复盘,差点丢了工作。
详解MySQL事务底层原理
一文讲清楚MySQL的所有锁
- 上一篇: I/O复用 - select&poll
- 下一篇: Mysql查询语句select教程
猜你喜欢
- 2024-11-21 死磕MySQL系列 一:原来一条select语句在MySQL是这样执行的
- 2024-11-21 不了解这5种查询类型,怎么在数据表中按需查询数据
- 2024-11-21 ANSYS 常见错误&警告解读
- 2024-11-21 EXCEL提取单元格中的中文、英文和数字
- 2024-11-21 数控机床的英文操作面板
- 2024-11-21 Mysql查询语句select教程
- 2024-11-21 Windows 10之查询OEM产品密钥的三种方法
- 2024-11-21 I/O复用 - select&poll
- 2024-11-21 如何选择执行程序代码,VBA编程Select语句介绍
- 2024-11-21 VBA中单元格区域的交集(intersect)
你 发表评论:
欢迎- 05-30壁纸|Q版灌篮高手
- 05-30Q版插画|今天的小姑娘有点小情绪,不爱笑,还是笑起来招人喜欢
- 05-30头像背景图|十二生肖Q版水墨(上)
- 05-308张Q版动漫人物-可爱的男生女生马克笔设计绘画,色彩漂亮鲜艳
- 05-30头像‖q卡通呆萌版
- 05-30Q版古风美人,十二花神系列,每一张都很可爱
- 05-30次元|动漫|Q版|萝莉|头像
- 05-30Q版古风人物|红楼梦系列 天上掉下来个林妹妹(附线稿)
- 最近发表
- 标签列表
-
- sd分区 (65)
- raid5数据恢复 (81)
- 地址转换 (73)
- 手机存储卡根目录 (55)
- tcp端口 (74)
- project server (59)
- 双击ctrl (55)
- 鼠标 单击变双击 (67)
- debugview (59)
- 字符动画 (65)
- flushdns (57)
- ps复制快捷键 (57)
- 清除系统垃圾代码 (58)
- web服务器的架设 (67)
- 16进制转换 (69)
- xclient (55)
- ps源文件 (67)
- filezilla server (59)
- 句柄无效 (56)
- word页眉页脚设置 (59)
- ansys实例 (56)
- 6 1 3固件 (59)
- sqlserver2000挂起 (59)
- vm虚拟主机 (55)
- config (61)
本文暂时没有评论,来添加一个吧(●'◡'●)