重复插入相同数据导致deadlock问题:Deadlock found when trying to get lock; try restarting transaction

article/2025/10/31 0:35:45

场景:

业务逻辑:第三方登录情况下,获取到用户的实名信息。之后判断该用户在用户表中是否存在,如果不存在或非实名,那么将其实名;如果已经实名,那么不做处理,直接登录。ORM使用的是spring data jpa,用户表在mobile字段上有唯一索引idx_mobile

发现不定期的发生业务报错:Deadlock found when trying to get lock; try restarting transaction

原因:

分析死锁日志

通过SHOW ENGINE INNODB STATUS;来查看死锁日志:

日志类似

注意:SHOW ENGINE INNODB STATUS\G 看到的DEADLOCK相关信息,只会返回最后的2个事务的信息,而其实有可能有更多的事务才最终导致的死锁

日志的上半部分说明事务1在等待什么锁

ip1 dbuser update

这个用户在执行下面这条sql语句

insert into 用户表 值1

其在申请idx_mobile索引的

RECORD LOCKS space id 3251 page no 14336 n bits 704 index `idx_mobile` of table 用户表 trx id 306872608 lock_mode X locks gap before rec insert intention waiting

这条插入记录的事务等待中,等待获得插入意向锁

 

日志的下半部分说明了事务2当前持有的锁以及等待的锁:

ip2 dbuser update

这个用户在执行下面这条sql语句

insert into 用户表 也是值1

HOLDS THE LOCK(S):

事务2持有S gap lock

lock mode S locks gap before rec

至于为什么加S Gap-Lock ,是因为在插入之前还需要多一步检查:如果记录中有唯一约束,判断存在一条记录等于当前插入的记录时,则需要在这个记录加上S Gap-Lock

也就是说事务1的insert intention lock等待事务2的s gap-lock释放

从日志的WAITING FOR THIS LOCK TO BE GRANTED块中我们可以看到事务2正在申请插入意向锁

那是什么原因造成这个dead lock呢?

事务0的回滚导致事务1和事务2的deadlock

为什么是事务0呢,看后面的参考就知道了,事务1和事务2的死锁是由于事务0rollback导致的

参考:

并发insert操作导致的dead lock

还原整个过程

第三方登录的情况下,前后端没有做重复提交的避免策略,这样会造成一个用户可以多次执行第三方登录的请求,当用户短时间内连续3次(或以上)执行第三方登录的请求,导致会起3个transaction(事务0 事务1 事务2)去执行insert操作

此时如果事务0由于业务代码问题rollback,会导致事务1和事务2 deadlock,直到mysql锁超时,报deadlock错误

即发生:当有3个(或以上)事务对相同的表进行insert操作,如果insert对应的字段上有uniq key约束并且第一个事务rollback了,那其中一个将返回死锁错误信息。

解决方案

避免此DEADLOCK;我们都知道死锁的问题通常都是业务处理的逻辑造成的,既然是uniq key,同时多台不同服务器上的相同程序对其insert一模一样的value,这本身逻辑就不太完美。故解决此问题:

思路1:

保证业务程序别在同一时间点并发的插入相同的值到相同的uniq key的表中

前端可以通过

1.提交数据之前判断当前提交按钮是否存在lock锁

2.在ajax提交之前给提交按钮上锁

3.ajax成功之后或者失败之后解锁

后端可以通过redis+aop来做

参考:redis防表单重复提交

思路2:

由于是事务0 rollback了才产生的deadlock,查明rollback的原因

 

我们的解决方法

我们现在是前端做重复提交的去重。

后端修改了可能产生rollback的逻辑

 


http://chatgpt.dhexx.cn/article/2Nx6Z4QF.shtml

相关文章

fatal error: all goroutines are asleep - deadlock

如题,近两天遇到此类错误,发现goroutine以及channel的基础仍需巩固。由该错误牵引出go相关并发操作的问题,下面做一些简单的tips操作和记录。 func hello() {fmt.Println("Hello Goroutine!") } func main() {go hello() // 启动另…

死锁问题(Deadlock)

4.8 死锁问题(Deadlock) 各进程在使用系统资源时,应注意系统产生死锁问题。下面先介绍什么是死锁。 4.8.1 死锁的概念  1. 死锁的定义 所谓死锁,是指各并发进程彼此互相等待对方所拥有的资源,且这些并发进程在得到对方的资源之前不会释…

SQL Server DeadLock 分析

1. 设置 XEvents 会话以收集死锁 1.1 扩展事件-会话-右键新建会话向导 1.2 设置会话名称 1.3 选择要捕获的事件 database_xml_deadlock_report 1.4 捕获全局字段 1.5 指定会话存储 1.6 结束 1.7 确保启动会话 2. 制造死锁 2.1 准备数据表及数据 2.1.1 准备数据库 TestBu…

MYSQL报错:MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting tr

mysql报错:MySQLTransactionRollbackException: Deadlock found when trying to get lock; try restarting transaction 报错情况:并发量大的情况对表的修改发生死锁 原因:查看了该更新语句的sql,没有设置主键,而mysq…

Deadlock的一些总结(死锁分析及处理)

1.1.1 摘要 在系统设计过程中,系统的稳定性、响应速度和读写速度至关重要,就像12306.cn那样,当然我们可以通过提高系统并发能力来提高系统性能总体性能,但在并发作用下也会出现一些问题,例如死锁。 今天的博文将着重介…

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

视频地址: https://www.bilibili.com/video/bv1zY411N7tB 最近在调试接口的时候遇到了MySQL死锁问题,我自己测试的时候一切都好好的,但在并发下,就死锁了 其实死锁问题,并没有一个类似“万金油”的解决办法&#xff0…

【死锁~】

死锁 死锁 死锁 1.死锁是什么? 当线程想要获取锁,但是获取失败,此时,线程进入阻塞状态,等待锁释放之后,线程获取锁。如果锁一直没有被释放,线程就一直处于阻塞状态。 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)

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

知识归纳:死锁

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

mmall数据库学习笔记

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

MMALL ADMIN 后台管理总结

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

mmall项目安装相关包文件

2019独角兽企业重金招聘Python工程师标准>>> 本步骤之前请先:建立相关文件夹(或者从git上clone项目下来),进入分支作业目录下运行个忠包文件的安装。注意:npm是所有安装的第一步 基础安装: 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…