首页 > 数据库 >Mysql死亡笔记的死锁记录

Mysql死亡笔记的死锁记录

时间:2023-10-21 20:04:24浏览次数:31  
标签:语句 insert 事务 笔记 死锁 user Mysql id

死锁记录

线上MySQL死锁了,我赶紧登录线上系统,查看业务日志。

Mysql死亡笔记的死锁记录_回滚

能清楚看到是这条insert语句发生了死锁。

MySQL如果检测到两个事务发生了死锁,会回滚其中一个事务,让另一个事务执行成功。很明显,我们这条insert语句被回滚了。

insert into user (id, name, age) values (6, '张三', 6);

但是我们怎么排查这个问题呢?

到底跟哪条SQL产生了死锁?

好在MySQL记录了最近一次的死锁日志,可以用命令行工具查看:

show engine innodb status;

Mysql死亡笔记的死锁记录_MySQL_02

在死锁日志中,可以清楚地看到这两条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) {
    // 如果userId不存在,就插入数据,否则更新     
    User userResult = userMapper.selectByIdForUpdate(user.getId());   
    if (userResult == null) {
        userMapper.insert(user);
    } else {
        userMapper.update(user);
    }
}

业务逻辑代码很简单,如果userId不存在,就插入数据,否则更新user对象数据。

从死锁日志中,我们看到有两条insert语句,很明显userId=5和userId=6的数据都不存在。

所以对应的SQL执行过程,可能就是这样的:

Mysql死亡笔记的死锁记录_MySQL_03

先用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]。

最后两个事务的执行过程就变成了:

Mysql死亡笔记的死锁记录_死锁_04

通过这个示例看到,两个事务都可以先后锁定 (1, 10]这个范围,说明MySQL默认加的临键锁的范围是可以交叉的。

那怎么解决这个死锁问题呢?

我能想到的解决办法就是,把这两个语句select和insert,合并成一条语句:

insert into user (id,name,age) values (5,'张三',5) 	
on duplicate key update name='张三',age=5;

大家有什么好的解决办法吗? 评论区给出您宝贵的意见!!

最后

本期结束咱们下次再见

标签:语句,insert,事务,笔记,死锁,user,Mysql,id
From: https://blog.51cto.com/yangbuyi/7969305

相关文章

  • 《信息安全系统与设计》第七周学习笔记
    多任务处理一般来说,多任务处理指的是同时进行几项独立活动的能力多任务处理是所有操作系统的基础,也是并行编程的基础进程的概念操作系统是一个多任务处理系统。在操作系统中,任务也称为进程进程的正式定义:进程是对映像的执行用一个简单的PROC结构体来表示进程typedefst......
  • 2023-2024-1 20211327 信息安全系统设计与实现 学习笔记6(必做)
    学习笔记6Unix/Linux系统多任务处理概述多任务处理系统Unix/Linux系统的进程管理实践过程Unix/Linux系统多任务处理概述1.进程管理:进程是程序的执行实例。Unix和Linux支持多个进程同时运行,每个进程都有自己的独立地址空间和资源。这使得多个应用程序可以同时运行,互不干......
  • 性能测试学习笔记(五)
    一、操作系统监控数值项模块监控命令CPUlscpu、cpuinfo、top、atop、vmstat、mpstat、pidstat、Dstat、Nmon、sar、cpupower、irqbalanceMemorytop、atop、vmstat、pidstat、Dstat、Nmon、sar、free、smemI/Oiostat、iotop、pidstat、Dstat、Nmon、sarNetwork......
  • 什么是MySQL索引下推优化
    索引条件下推优化(IndexConditionPushdown(ICP))是MySQL5.6添加的,用于优化数据查询。不使用索引条件下推优化时存储引擎通过索引检索到数据,然后返回给MySQLServer,MySQLServer进行过滤条件的判断。当使用索引条件下推优化时,如果存在某些被索引的列的判断条件时,MySQLServer将......
  • php js + laravel + mysql开发的手术麻醉临床信息系统源码
    手术麻醉临床信息系统有着完善的临床业务功能,能够涵盖整个围术期的工作,能够采集、汇总、存储、处理、展现所有的临床诊疗资料。通过该系统的实施,能够规范麻醉科的工作流程,实现麻醉手术过程的信息数字化,自动生成麻醉的各种医疗文书,完成共享HIS、LIS、PACS和EMR等手术患者信息,从而提......
  • uboot为LED添加DM驱动--Apple的学习笔记
    一,前言开始玩所有板子一般都是先点灯,比如我可以在汇编中点灯,可以在board_init中用writel写寄存器点灯,当我要进一步熟悉下设备树驱动模型,不管学习linux还是学习uboot这块我理解类似,所以我要通过添加设备树及配置开关来实现默认打开led0和led1的功能。二,实现的过程1,先有了dts信息,我从......
  • 学习笔记六
    学习笔记六一.作业要求自学教材第3章,提交学习笔记(10分),评分标准如下知识点归纳以及自己最有收获的内容,选择至少2个知识点利用chatgpt等工具进行苏格拉底挑战,并提交过程截图,提示过程参考下面内容(4分)“我在学***X知识点,请你以苏格拉底的方式对我进行提问,一次一个问题”核......
  • UBUNTU下第一次写简单驱动(笔记)
    一、环境Ubuntu14.04+vmwaretools二、步骤先写个.c文件,驱动文件一般没有printf,有自己的一套,先写一个helloword.c /* *helloworld.c * *宇文凌风 * */     #include"linux/init.h" #include......
  • 学习笔记6
    第三章学习总结多任务处理一般指的是同时进行几项独立活动的能力,这种逻辑并行性称为“并发”。进程的概念进程是对映像的执行每个进程用一个独特的数据结构表示,称为进程控制块(PCB)或任务控制块(TCB),本书称为PROC结构体。如下是一个非常简单的PROC结构体:next:指向下一个PROC......
  • 《信息安全系统设计与实现》第七周学习笔记
    《信息安全系统设计与实现》第七周学习笔记第三章Unix/Linux进程管理多任务处理多任务处理简单说,就是同一时间给多个程序运行处理数据。即使在系统中通常有许多其他的程序在运行,但进程也可以向每个程序提供一种假象,仿佛它在独占地使用处理器。但事实上进程是轮流使用处理器的......