昨晚我正在床上睡得着着的,突然来了一条短信。

啥,线上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;

大家有什么好办法吗?

这个死锁情况,还是挺常见的,赶紧回去翻一下项目代码有没有这样的问题。

文章持续更新,可以微信搜一搜「 一灯架构 」第一时间阅读更多技术干货。

记一次排查线上MySQL死锁过程,不能只会curd,还要知道加锁原理的更多相关文章

  1. 一次线上mysql死锁分析

    一.现象 发运车次调用发车接口时发生异常,后台抛出数据库死锁日志. 二.原因分析 通过日志可以看出事务T1等待 heap no 8的行锁 (X locks 排他锁) 事务T2持有heap no 8的行 ...

  2. 记一次linux通过jstack定位CPU使用过高问题或排查线上死锁问题

    一.java定位进程 在服务器中终端输入命令:top 可以看到进程ID,为5421的cpu这列100多了. 记下这个数字:5421 二.定位问题进程对应的线程 然后在服务器中终端输入命令:top -H ...

  3. 原创 记录一次线上Mysql慢查询问题排查过程

    背景 前段时间收到运维反馈,线上Mysql数据库凌晨时候出现慢查询的报警,并把原始sql发了过来: --去除了业务含义的sql update test_user set a=1 where id=1; ...

  4. 线上Mysql数据库崩溃事故的原因和处理

    前文提要 承接前文<一次线上Mysql数据库崩溃事故的记录>,在文章中讲到了一次线上数据库崩溃的事件记录,建议两篇文章结合在一起看,不至于摸不着头脑. 由于时间原因,其中只讲了当时的一些经 ...

  5. Spring+SpringMVC+MyBatis+easyUI整合进阶篇(八)线上Mysql数据库崩溃事故的原因和处理

    前文提要 承接前文<一次线上Mysql数据库崩溃事故的记录>,在文章中讲到了一次线上数据库崩溃的事件记录,建议两篇文章结合在一起看,不至于摸不着头脑. 由于时间原因,其中只讲了当时的一些经 ...

  6. Linux命令排查线上问题常用的几个

    排查线上问题常用的几个Linux命令 https://www.cnblogs.com/cjsblog/p/9562380.html top 相当于Windows任务管理器 可以看到,输出结果分两部分, ...

  7. 记一次线上MySQL数据库死锁问题

            最近线上项目报了一个MySQL死锁(DealLock)错误,虽说对业务上是没有什么影响的,由于自己对数据库锁这块了解不是很多,之前也没怎么的在线上碰到过.这次刚好遇到了,便在此记录一下 ...

  8. 一则线上MySql连接异常的排查过程

    Mysql作为一个常用数据库,在互联网系统应用很多.有些故障是其自身的bug,有些则不是,这里以前段时间遇到的问题举例. 问题 当时遇到的症状是这样的,我们的应用在线上测试环境,JMeter测试过程中 ...

  9. 一次线上Mysql数据库崩溃事故的记录

    文章简介 工作这几年,技术栈在不断更新,项目管理心得也增加了不少,写代码的速度也在提升,感觉很欣慰,毕竟是在一直进步,但是过程中也有许许多多的曲折,也踩过了数不尽的坑坑洼洼,从一个连百度都不知道用的萌 ...

随机推荐

  1. .NET Core(.NET6)中gRPC使用

    一.简介 简单解析一下gRPC,gRPC 是一个由Google开源的,跨语言的,高性能的远程过程调用(RPC)框架. 特点: 跨语言 内容protobuf格式(比json体积小),网络传输快 使用HT ...

  2. formData一般用法,移动端,pc端都可以用,pc有兼容性问题

    其实FormData是一个 对象他是一个比较新的东东(其实我也不知道改叫什么好) 利用FormData对象,你可以使用一系列的键值对来模拟一个完整的表单,然后使用XMLHttpRequest发送这个& ...

  3. python基础练习题(题目 斐波那契数列II)

    day16 --------------------------------------------------------------- 实例024:斐波那契数列II 题目 有一分数序列:2/1,3 ...

  4. v74.01 鸿蒙内核源码分析(编码方式篇) | 机器指令是如何编码的 | 百篇博客分析OpenHarmony源码

    本篇关键词:指令格式.条件域.类型域.操作域.数据指令.访存指令.跳转指令.SVC(软件中断) 内核汇编相关篇为: v74.01 鸿蒙内核源码分析(编码方式) | 机器指令是如何编码的 v75.03 ...

  5. petite-vue源码剖析-沙箱模型

    在解析v-if和v-for等指令时我们会看到通过evaluate执行指令值中的JavaScript表达式,而且能够读取当前作用域上的属性.而evaluate的实现如下: const evalCache ...

  6. Day 006:PAT练习--1005 Spell It Right (20 分)

    上星期一直在写报告乱七八糟的,从今天开始不刷乙级的了,还是多刷甲级进步来得快一点! 显而易见,该题的关键在于将输入之和的每一位从高到低输出,这里我们发现题意中的输入数的范围为0-10^100,显然我们 ...

  7. XCTF练习题---MISC---Excaliflag

    XCTF练习题---MISC---Excaliflag flag:3DS{Gr4b_Only_th1s_B1ts} 解题步骤: 1.观察题目,下载附件 2.拿到手以后是一张图片,话不多说,直接上Ste ...

  8. 【问题解决】'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed.

    问题复述 今天项目组有人找我说之前部署的程序在测试环境没问题,到生产环境出现了奇怪的问题,点按钮没反应. 我通过腾讯会议发现他们的浏览器控制台上打出了如下错误: Access to XMLHttpRe ...

  9. 快速创建简单的mybatis应用

    1.导包(配置pom.xml) 一定要用这个网站:https://mvnrepository.com/ 点击查看代码 <dependency> <groupId>org.myb ...

  10. 详解六大国产CPU处理器

    一个执着于技术的公众号 CPU作为计算机设备的运算和控制核心,负责指令读取.译码与执行,因研发门槛高.生态构建难,被认为是集成电路产业中的"珠穆朗玛峰". 纵观全球,Intel.A ...