Deadlock found when trying to get lock; try restarting transaction 【MySQL死锁问题解决】

article/2025/10/31 0:46:52

视频地址: https://www.bilibili.com/video/bv1zY411N7tB



最近在调试接口的时候遇到了MySQL死锁问题,我自己测试的时候一切都好好的,但在并发下,就死锁了

其实死锁问题,并没有一个类似“万金油”的解决办法,解铃还需系铃人,能做的只有写这个代码的人自己去解决

第一次出现死锁,想必你也会和我一样整个人都是懵的,不知道如何下手,等你看过下面的文章明白了死锁,就不会害怕了

死锁异常

2022-06-15 16:05:22.216 ERROR 38907 --- [  XNIO-1 task-4] c.i.c.exception.GlobalExceptionHandler   : 
### Error updating database.  Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
### The error may exist in file [/Users/xiaodaoxian/Desktop/work/code/ideamake-market-cloud-third-dock/target/classes/mapper/YxxWkBatchDataMapper.xml]
### The error may involve defaultParameterMap
### The error occurred while setting parameters
### SQL: DELETE FROM xdx_test_two WHERE user_id = ?
### Cause: com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction
; Deadlock found when trying to get lock; try restarting transaction; nested exception is com.mysql.cj.jdbc.exceptions.MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction

一、理论(重要)

所谓的死锁,一定是两个线程互相等待对方的资源。对于MySQL 来说,那就是两个事物锁住了对方的数据。

MySQL的innodb有 表锁、行锁,如果锁表那死锁的概率很大,一般我们操作都是带有参数的 where user_id = 'xxx'

理论上如果写delete or update 的时候带了上面的条件,按照我们的理解那就是行锁,并发情况下只要我们参数不一致那永远不会造成死锁

但实际情况总不会如人意的,我造成死锁的2个SQL就是上面这样的操作,两个删除都是带了 where,但还是锁表了


MySQL InnoDB 引擎下,delete/update操作where后面的条件如果没有走索引,会锁表(MySQL 5.6/7 版本验证)


请注意上面我说的是 两个事物互相锁住了对方的资源 而并不是简单的两个SQL,这也就是为什么需要熟悉业务代码的人去解决,一个复杂的业务可能涉及到七八张表的操作。


上面说了死锁产生的主要原因,下面再来说说死锁在业务中产生的几种可能和解决办法

  1. 一般来说我们代码不管哪个线程进来都是按顺序执行的,但实际情况是我们在代码中写了各种 if else 等条件语句,这样就导致每个请求实际操作表的顺序可能不一致了,就可能造成死锁(我遇到就是这样的),但这种情况大部分我们把表索引创建好,不出现锁表就没事了。
  2. 并发下相同的业务参数去执行,第一个事物还没提交后面的事物又来了,这种我们加分布式锁就好了

二、死锁实践

2-1、建表

CREATE TABLE `xdx_test_one` (`id` int(11) NOT NULL AUTO_INCREMENT,`user_id` varchar(32) DEFAULT NULL COMMENT '用户uuid',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4 COMMENT='测试表one';CREATE TABLE `xdx_test_two` (`id` int(11) NOT NULL AUTO_INCREMENT,`user_id` varchar(32) DEFAULT NULL COMMENT '用户uuid',PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=7 DEFAULT CHARSET=utf8mb4 COMMENT='测试表two';

2-2、代码

2-2-1、controller

@GetMapping("/testLock")
public void testLock(@RequestParam String params) throws InterruptedException {dataServiceImpl.testLock(params);
}

2-2-2、service

@Transactional(rollbackFor = Exception.class)
public void testLock(String params) throws InterruptedException {if ("one".equals(params)) {dataMapper.deleteOne(UUID.randomUUID().toString().substring(10, 18));System.out.println(params + " 获取 xdx_test_one 表锁");Thread.sleep(2000);}dataMapper.deleteTwo(UUID.randomUUID().toString().substring(10, 18));System.out.println(params + " 获取 xdx_test_two 表锁");if ("two".equals(params)) {dataMapper.deleteOne(UUID.randomUUID().toString().substring(10, 18));System.out.println(params + " 获取 xdx_test_one 表锁");}
}

2-2-3、mapper

<delete id="deleteOne">DELETE FROM xdx_test_one WHERE user_id = #{substring}
</delete><delete id="deleteTwo">DELETE FROM xdx_test_two WHERE user_id = #{substring}
</delete>

2-3、测试

按照顺序快速的请求下面的url, 你就会看到上面的异常了

http://127.0.0.1:8080/testLock?parmas=one
http://127.0.0.1:8080/testLock?parmas=two

2-4、其它

我们要解决上面的死锁其实很简单,只需要给上面的 user_id 加一个索引就好了


三、死锁分析


3-1、阿里云日志分析

死锁我们一般是要看日志进行分析处理,其实只要找到两个事物之间谁拥有了对方的哪个锁即可,但原始的MySQL日志不大好看,刚好我们是使用的阿里云的服务版MySQL,它会把死锁日志进行分析以表格的方式展示,刚刚我们测试的死锁,表格呈现如下

在这里插入图片描述

可以先大致看一下这个表结构,应该是很清晰的,不过这个表是存在一点问题的,那就是 事物1 是持有 yx_mc.xdx_test_two 的锁 不然是不构成死锁,这个阿里云解释说我们使用的数据库版本比较老,在新的版本已经解决了这个问题。


3-2、原始日志分析

看完了上面的表,我们对死锁的组成应该有了进一步的理解,下面我们来看看MySQL的原始死锁日志

------------------------
LATEST DETECTED DEADLOCK
------------------------
2022-06-16 17:25:01 7fde0b4a3700
*** (1) TRANSACTION:
TRANSACTION 36291462, ACTIVE 0.717 sec fetching rows
mysql tables in use 1, locked 1
LOCK WAIT 5 lock struct(s), heap size 1184, 6 row lock(s), undo log entries 5
LOCK BLOCKING MySQL thread id: 576129097 block 307687953
MySQL thread id 307687953, OS thread handle 0x7fdeda9fa700, query id 1317704191 10.19.22.58 yx_property_test updating
DELETE FROM xdx_test_one WHERE user_id = '11111'
*** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 3212 page no 3 n bits 88 index `PRIMARY` of table `yx_mc`.`xdx_test_one` trx id 36291462 lock_mode X locks rec but not gap waiting
Record lock, heap no 12 PHYSICAL RECORD: n_fields 4; compact format; info bits 320: len 4; hex 8000000b; asc     ;;1: len 6; hex 00000229c378; asc    ) x;;2: len 7; hex 0f0000001b0c25; asc       %;;3: len 5; hex 3131313131; asc 11111;;*** (2) TRANSACTION:
TRANSACTION 36291448, ACTIVE 2.005 sec fetching rows
mysql tables in use 1, locked 1
5 lock struct(s), heap size 1184, 7 row lock(s), undo log entries 6
MySQL thread id 576129097, OS thread handle 0x7fde0b4a3700, query id 1317704227 10.19.22.58 yx_property_test updating
DELETE FROM xdx_test_two WHERE user_id = '22222'
*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 3212 page no 3 n bits 88 index `PRIMARY` of table `yx_mc`.`xdx_test_one` trx id 36291448 lock_mode X locks rec but not gap
Record lock, heap no 12 PHYSICAL RECORD: n_fields 4; compact format; info bits 320: len 4; hex 8000000b; asc     ;;1: len 6; hex 00000229c378; asc    ) x;;2: len 7; hex 0f0000001b0c25; asc       %;;3: len 5; hex 3131313131; asc 11111;;Record lock, heap no 13 PHYSICAL RECORD: n_fields 4; compact format; info bits 320: len 4; hex 8000000c; asc     ;;1: len 6; hex 00000229c378; asc    ) x;;2: len 7; hex 0f0000001b0c48; asc       H;;3: len 5; hex 3131313131; asc 11111;;Record lock, heap no 14 PHYSICAL RECORD: n_fields 4; compact format; info bits 320: len 4; hex 8000000d; asc     ;;1: len 6; hex 00000229c378; asc    ) x;;2: len 7; hex 0f0000001b0c6b; asc       k;;3: len 5; hex 3131313131; asc 11111;;Record lock, heap no 15 PHYSICAL RECORD: n_fields 4; compact format; info bits 320: len 4; hex 8000000e; asc     ;;1: len 6; hex 00000229c378; asc    ) x;;2: len 7; hex 0f0000001b0c8e; asc        ;;3: len 5; hex 3131313131; asc 11111;;Record lock, heap no 16 PHYSICAL RECORD: n_fields 4; compact format; info bits 320: len 4; hex 8000000f; asc     ;;1: len 6; hex 00000229c378; asc    ) x;;2: len 7; hex 0f0000001b0cb1; asc        ;;3: len 5; hex 3131313131; asc 11111;;Record lock, heap no 17 PHYSICAL RECORD: n_fields 4; compact format; info bits 320: len 4; hex 80000010; asc     ;;1: len 6; hex 00000229c378; asc    ) x;;2: len 7; hex 0f0000001b0cd4; asc        ;;3: len 5; hex 3131313131; asc 11111;;*** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 3213 page no 3 n bits 88 index `PRIMARY` of table `yx_mc`.`xdx_test_two` trx id 36291448 lock_mode X locks rec but not gap waiting
Record lock, heap no 18 PHYSICAL RECORD: n_fields 4; compact format; info bits 320: len 4; hex 80000017; asc     ;;1: len 6; hex 00000229c386; asc    )  ;;2: len 7; hex 190000002116e0; asc     !  ;;3: len 5; hex 3232323232; asc 22222;;*** WE ROLL BACK TRANSACTION (1)

N、其它

N-1、是不是真的需要事物

其实我们可以反过来想一想,我们的代码是不是一定要加锁,有时候一个复杂的业务,你加锁,会不断的出现死锁,很难根除。

换个角度,如果我们去掉事物,是不是就没有死锁了?你可能觉得不加事物数据会异常,但是想一想如果频繁产生死锁你的数据不也没办法保证吗?如果我们把所有的异常都解决是不是就没问题了?


N-2、拆分事物的颗粒度

同上一个,如果事物粒度太大了,造成死锁的可能性就很大。我们可以根据业务去进行细分,把一个大的事物拆分成多个小的事物,以此来减少死锁的可能性。


N-3、如果只有一个表是否会死锁

只操作一个表是不会死锁的,第一个事物获取了锁,第二个事物就会进入等待,所以不会出现死锁。


N-4、同一个代码是不是一定会造成死锁

我们知道MySQL里面有一个关键字 EXPLAIN ,它可以分析SQL执行的结果,但实际上一定就按照这个去执行么?其实不然的,还有一个SQL优化器,最终执行的方式是由它来决定的。

上面同样的代码,在我本地数据库 where 后面的条件不管是什么都会造成死锁,而在阿里云的数据库上不会,必须要扫描到真实存在数据才会死锁。


N-5、产生死锁的两个事物怎么办?

从目前的数据来看,事物1 会执行成功,事物2 会回滚


http://chatgpt.dhexx.cn/article/ucUk97Vo.shtml

相关文章

【死锁~】

死锁 死锁 死锁 1.死锁是什么? 当线程想要获取锁&#xff0c;但是获取失败&#xff0c;此时&#xff0c;线程进入阻塞状态&#xff0c;等待锁释放之后&#xff0c;线程获取锁。如果锁一直没有被释放&#xff0c;线程就一直处于阻塞状态。 2.死锁的条件 1.互斥作用:一个线程获…

Mysql报Deadlock found when trying to get lock; try restarting transaction问题解决

Mysql报Deadlock found when trying to get lock; try restarting transaction问题解决!! 文章目录 问题发生场景Mysql锁类型分析死锁原理问题排查过程问题原因解决方法经验教训查看mysql死锁日志 问题发生场景 今天记录一下最近项目中遇到的一个问题,前几天在部署项目后,在线…

死锁(Deadlock)

什么是死锁 死锁是指两个或两个以上的线程在执行过程中&#xff0c;因争夺资源而造成的一种互相等待的现象。若无外力作用&#xff0c;它们都将无法推进下去。 产生死锁的四个必要条件得烂熟于心 互斥条件&#xff1a;进程要求对所分配的资源进行排他性控制&#xff0c;即在一段…

知识归纳:死锁

一. 死锁定义 死锁(Deadlock)是指两个或两个以上的进程在执行过程中&#xff0c;由于竞争资源或者由于彼此通信而造成的一种阻塞的现象&#xff0c;若无外力作用&#xff0c;它们都将无法推进下去。 举例:毕业生找工作,公司表示只需要有工作经验才可以来;要想有工作经验,就需要…

mmall数据库学习笔记

mmall数据库学习笔记 文章目录 mmall数据库学习笔记唯一索引产品表购物车表支付信息表订单表订单明细表收货地址表外键 唯一索引 在用户表中&#xff0c;设置了用户名作为唯一索引&#xff0c;理由如下&#xff1a;用户名是不允许重复的&#xff0c;那么当不是分布式开发的时候…

MMALL ADMIN 后台管理总结

后台管理项目前期准备 1&#xff0c;vue-cli2 项目框架 2&#xff0c;下载axios插件 cnpm install axios&#xff0c;安装Element.ui &#xff0c; vue-cli2中使用scss 注意版本 cnpm install sass-loader7.1.0 --save-dev &#xff08;8.0.0&#xff09; v…

mmall项目安装相关包文件

2019独角兽企业重金招聘Python工程师标准>>> 本步骤之前请先&#xff1a;建立相关文件夹&#xff08;或者从git上clone项目下来&#xff09;&#xff0c;进入分支作业目录下运行个忠包文件的安装。注意&#xff1a;npm是所有安装的第一步 基础安装&#xff1a; 1.np…

mmall电商项目学习笔记之 idea,maven工程整合ssm框架

项目目录结构 1.pom文件导入jar包 1.1 <properties><!--设置编码格式--><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><!--sprin…

Demo_mmall v2.0 (四) Tomcat集群演进及使用Redis进行session重构实现单点登录

小谈mmall架构演进 上回书和上上回书说到redis的用法还有在代码里怎么操作Redis数据库&#xff0c;学完了得用啊。怎么用啊&#xff1f;这得从项目架构说起了。 mmall是一个简单的用SSM搭建起来的基本只能本地玩耍的电商DEMO&#xff0c;最简单的架构版本V1.0是这样婶的&#…

自学实践前后端项目4 MMall商城 2

一。搭建静态页面 1)UserController里面实现登录操作 Autowired private UserService userService;PostMapping("/login") public String login(String loginName, String password, HttpSession session){QueryWrapper wrapper new QueryWrapper();wrapper.eq(&q…

mmall用户模块

mmall用户模块 user数据表设计用户模块接口文档服务端响应对象&#xff08;ServerResponse< T>&#xff09;响应对象封装以下3个属性判断响应是否成功私有化构造函数&#xff0c;对外暴露静态方法返回所需要的响应对象&#xff0c;例如&#xff1a;响应成功响应失败 Resp…

自学实践前后端项目4 MMall商城 7

一。地址管理 1.前端改为 userAddress 2. OrderController增加两个需要的元素 3.接口 服务也加上去 4. 在OrderServiceImpl实现层判断是否为新地址再进行保存 //先判断新老地址 if (orders.getUserAddress().equals("newAddress")){//存入数据库UserAddress use…

自学实前后端践项目4 MMall商城 1

一.开发环境 1.JDK8以上Spring Boot 2.3.0ThymeleafMyBatis Plus3.3.1MySQL8.0 2.部署&#xff1a;Linux,&#xff0c;&#xff08;阿里云 腾讯云&#xff09;JDK8&#xff0c;MySQL8.0 3.部署方式&#xff1a;jar包部署&#xff0c;不需要Tomcat 二.新建工程 1&#xff0…

mmall电商项目学习笔记之mybatis三剑客

一.Mybatis plugin IDEA 2017.3版本下Mybatis plugin 3.53安装使用 插件下载地址 http://www.awei.org/download/iMybatis-3.21.jar 二.MyBatis-Generate 反向生成 【转】mybatis自动生成实体代码的插件 【method2】逆向生成 2.1 在pom.xml中做两处配置 2.1.1配置depen…

自学实践前后端项目4 MMall商城 4

一。实现商品详情展示 1.测试获取后台当个商品的信息 2.实现通过点击商品名称和商品图片进入商品详情页面 1&#xff09;查找出商品信息 2&#xff09;在前端进行映射 3&#xff09;设置库存选择限制 判断逻辑 $(function(){//给type绑定点击事件$(".type").click…

mmall 项目实战(一)项目初始化

1.创建 数据库 及 表 数据脚本&#xff1a; /* Navicat Premium Data Transfer Source Server : 182.92.82.103 Source Server Type : MySQL Source Server Version : 50173 Source Host : 182.92.82.103 Source Database : mmall Target Se…

B2C购物商城---MMALL商城概览

注意&#xff1a; 商品小图原图缺失后续上传到图片服务器。不影响使用支付宝二维码是支付宝沙箱开发环境生成&#xff0c;不会产生真实交易&#xff0c;若需体验&#xff0c;请下载支付宝沙箱版扫描体验项目仍需优化 本项目的完成参考了慕课网happymmall的设计 项目源码在&…

MMall项目完整分析总结

Linux服务器 线上环境&#xff1a; 1.jdk 2.vsftpd 3.nginx 4.mysql 5.tomcat 6.git 7.maven 8.Redis 项目采用Tomcat集群方式: 在此架构图中&#xff0c;nginx使用的是轮询的负载均衡策略。session不交给tomcat自己管理&#xff0c;已经交由左侧的redis分布式…

python flask-sqlalchemy flask-marshmallow基本使用

首先安装 pip install marshmallow-sqlalchemy pip install flask-sqlalchemy pip install flask-marshmallow 参考 sqlalchemy query 官网 app.py文件内容 from flask import Flask,jsonify import config from flask_sqlalchemy import SQLAlchemy from flask_marshmallow i…

Flask_使用flask_marshmallow序列化数据

代码如下&#xff1a; from flask import Flask from flask_marshmallow import Marshmallow from flask_sqlalchemy import SQLAlchemy from marshmallow import fieldsapp Flask(__name__) app.config["SQLALCHEMY_DATABASE_URI"] "mysqlpymysql://root:12…