如何与死锁斗争!!!

其他系列文章导航

Java基础合集

设计模式合集

多线程合集

分布式合集

ES合集


文章目录

其他系列文章导航

文章目录

前言

一、死锁场景现场

二、死锁是如何产生的

三、死锁排查思路

四、sql模拟死锁复现

五、死锁的解决方案


前言

为避免影响业务,应尽可能避免修改线上数据库的字段,因为这可能导致锁表并可能导致死锁。

但是如果数据库确实出现了死锁,就需要采取相应的排查思路来解决问题,以恢复业务的正常运行。

本文将分享一些有关数据库死锁排查的思路和方法,以便在出现问题时能够有足够的把握解决它们。


一、死锁场景现场

模拟场景:对用户数据进行迁移。

把业务礼物表A的数据删除,然后修改用户ID后,然后插入到礼物B表。其中,A表和B表,表示同一个礼物逻辑表下的不同分表

CREATE TABLE `gift` (`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',`sender_id` int DEFAULT NULL COMMENT '赠送者ID',`gift_type` varchar(50) NOT NULL COMMENT '礼物类型',`gift_id` varchar(50) NOT NULL COMMENT '礼物ID',`gift_name` varchar(100) NOT NULL COMMENT '礼物名称',`created_time` datetime DEFAULT NULL COMMENT '创建时间',`updated_time` datetime DEFAULT NULL COMMENT '更新时间',`gift_send_time` datetime DEFAULT NULL COMMENT '礼物赠送时间',`quantity` int DEFAULT NULL COMMENT '礼物数量',`receiver_id` int DEFAULT NULL COMMENT '接收者ID',`message` text COMMENT '消息',`status` varchar(20) DEFAULT NULL COMMENT '状态',`expiry_time` datetime DEFAULT NULL COMMENT '过期时间',`channel_no` varchar(50) DEFAULT NULL COMMENT '渠道',`flow_no` varchar(50) NOT NULL COMMENT '流水号',PRIMARY KEY (`id`),UNIQUE KEY `idx_unique_flow_no` (`flow_no`)
)

在进行礼物流水表数据迁移的过程中,出现了 死锁等待超时 的场景。 

从日志可以看出,是在执行礼物赠送流水表删除的时候,阻塞等待,最后锁等待超时了。出现这种情况,一般都是因为产生了死锁。 

既然是死锁,为什么出现的却是Lock wait timeout exceeded; try restarting transaction 锁等待超时这个日志呢?这是因为在Innodb存储引擎中,当检测到死锁时,它会尝试自动解决死锁问题,通常是通过回滚(rollback)其中的一个或者多个事务来解除死锁。 


二、死锁是如何产生的

死锁产生的条件包括:

  • 互斥条件:至少有一个资源是独占的,即一次只能被一个进程或线程使用。

  • 持有和等待条件:一个进程或线程可以持有一个资源,并等待其他进程或线程持有的资源。

  • 非抢占条件:已经分配给一个进程或线程的资源不能被强制性地抢占,只能由持有资源的进程或线程显式释放。

  • 循环等待条件:一系列进程或线程形成循环等待其他进程或线程持有的资源。


三、死锁排查思路

死锁的排查思路:

  1. show engine innodb status,查看最近一次死锁日志。

  2. 分析死锁日志,找到关键词TRANSACTION。

  3. 分析死锁日志,查看正在执行的SQL。

  4. 看它持有什么锁,等待什么锁。

顺着这个排查思路,我们先复现这个死锁案例。在删除礼物赠送流水表阻塞等待的过程,执行show engine innodb status命令,查看事务和锁的信息。

通过日志,看到这个事务正在执行的SQL是:

DELETE FROM gift_send_flow_0 WHERE flow_no = 'flowNo666' AND sender_id = 10000

它在等待一个idx_unique_flow_no的排他行锁。那么到底是什么SQL持有了这个锁,导致它阻塞等待呢,这时候,我们联系上下文代码,把操作这个表相关的插入或者修改、删除的SQL都梳理一下,最后发现是一条插入的SQL涉及到: 

 <insert id="insertGiftSendFlow" parameterType="com.example.demo.generate.GiftSendFlowTab">INSERT INTO gift_send_flow (id,gift_type, gift_id, gift_name, created_time, updated_time,gift_send_time, quantity, sender_id, receiver_id, message, status, expiry_time, channel_no,flow_no)VALUES (#{id},#{giftType}, #{giftId}, #{giftName}, #{createdTime}, #{updatedTime},#{giftSendTime}, #{quantity}, #{senderId}, #{receiverId}, #{message}, #{status}, #{expiryTime}, #{channelNo},#{flowNo})</insert>

 我们迁移的过程,涉及把原来记录删除掉,然后替换senderId,再执行插入。基本确定就是删除和插入的SQL形成的死锁。我们再来本地模拟这两条SQL的并发执行。


四、sql模拟死锁复现

先开启一个事务A,执行删除,插入:

mysql> BEGIN;
Query OK, 0 rows affected (0.01 sec)mysql> DELETE FROM gift_send_flow_0 WHERE flow_no = 'flowNo666' AND sender_id = 10000;
Query OK, 1 row affected (0.00 sec)mysql> INSERT INTO gift_send_flow_0 (id,gift_type, gift_id, gift_name, created_time, updated_time, gift_send_time, quantity, sender_id, receiver_id, message, status , expiry_time, channel_no,flow_no) VALUES (null,'虚拟', '1', '玫瑰花', '2023-11-21 22:57:28', '2023-11-21 22:57:28', '2023-11-21 22:57:28', 1,  170000, 10025, '送给女嘉宾', NULL , NULL,'1000','flowNo666');
Query OK, 1 row affected (0.01 sec)

另开一个事务,再执行删除、插入,发现在执行删除的时候,就进入了阻塞等待。

mysql> begin;
Query OK, 0 rows affected (0.00 sec)mysql> DELETE FROM gift_send_flow_0 WHERE flow_no = 'flowNo666' AND sender_id = 10000;
ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction

通过show engine innodb status查看死锁日志与上面场景的日志相同。

为了进一步验证,可以通过这个命令(MySQL 8.0+)查看SQL加锁情况:

SELECT * FROM performance_schema.data_locks\G;

会发现INSERT语句的时候,持有了唯一索引的排他行锁,然后DELETE的时候,也需要获取这个锁,因此形成死锁循环等待。 


五、死锁的解决方案

因为并发执行删除和插入同一个表,因此形成死锁

死锁的方案解决方案有:

  • 避免循环等待:保证资源分配的有序性,例如,定义一个全局的资源申请顺序,并要求所有进程按照这个顺序申请资源。这样可以避免循环等待的情况。

  • 资源有序性:按照固定的顺序获取资源,避免多个进程在不同的顺序下请求资源,导致循环等待的情况。

  • 超时机制:当一个进程无法获取所需资源时,设置一个超时机制,超过一定时间后放弃等待的资源并释放自己所持有的资源,避免长时间等待。

回到本文的案例,那就是 迁移数据的时候控制有序性,串行执行就好

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/175303.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Django回顾【一】

一、Web应用程序 Web应用程序是一种可以通过Web访问的应用程序&#xff0c;程序的最大好处是用户很容易访问应用程序&#xff0c;用户只需要有浏览器即可&#xff0c;不需要再安装其他软件。应用程序有两种模式C/S、B/S。 C/S&#xff1a;客户端<----->服务端 例如My…

分类预测 | Matlab实现NGO-KELM北方苍鹰算法优化核极限学习机分类预测

分类预测 | Matlab实现NGO-KELM北方苍鹰算法优化核极限学习机分类预测 目录 分类预测 | Matlab实现NGO-KELM北方苍鹰算法优化核极限学习机分类预测分类效果基本描述程序设计参考资料 分类效果 基本描述 1.Matlab实现NGO-KELM北方苍鹰算法优化核极限学习机分类预测&#xff08;完…

App的测试,和传统软件测试有哪些区别?应该增加哪些方面的测试用例?

从上图可知&#xff0c;测试人员所测项目占比中&#xff0c;App测试占比是最高的。 这就意味着学习期间&#xff0c;我们要花最多的精力去学App的各类测试。也意味着我们找工作前&#xff0c;就得知道&#xff0c;App的测试点是什么&#xff0c;App功能我们得会测试&#xff0…

Ansible的module_defaults

环境 管理节点&#xff1a;Ubuntu 22.04控制节点&#xff1a;CentOS 8Ansible&#xff1a;2.15.6 module_defaults 如果某个module被多次调用&#xff0c;且每次调用时的参数也一样&#xff0c;则可以通过 module_defaults 为该module指定缺省参数&#xff0c;以简化操作。 …

Unreal Engine 学习笔记 (4)—— 多方向动画

1.创建混合空间 1.设置水平方向命名为Direction表示行进方向 -45,300表示向左前方45度方向行走-90,300表示向正左方90度方向行走-135,300表示向左后方45度方向行走-180,300表示向正后方行走右侧方向动画与上述左侧使用同样方法设置Run动画与Walk动画使用同样方法设置 2. 设置…

uniapp使用map标签

在UniApp中&#xff0c;可以使用map标签来显示地图&#xff0c;并通过其属性来自定义地图的样式和行为。以下是一些常用的map标签属性&#xff1a; id&#xff1a;用于给地图组件指定一个唯一的标识符&#xff0c;方便在代码中进行引用和操作。 style&#xff1a;用来设置地图…

【ARM AMBA AXI 入门 17 - AXI4 AWUSER | ARUSER 详细介绍】

文章目录 AWUSER | ARUSER 详细介绍AWUSERConfigurationUser signalsARUSERAWUSER 和 ARUSER 使用举例AWUSER | ARUSER 详细介绍 在 ARM AMBA AXI 协议中可以包含一组用户自定义信号,叫做 User signals,比如 AWUSER 和 ARUSER 信号,它们分别与写地址(AW)和读地址(AR)通…

Java游戏 王者荣耀

GameFrame类 所需图片&#xff1a; package 王者荣耀;import java.awt.*; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.KeyAdapter; import java.awt.event.KeyEvent; import java.io.File; import java.util.ArrayList…

某思路等考通一级MSOffice的分析

看到有朋友寻求2021版的等级考试一级软件&#xff0c;秉承授人以鱼不如授人以渔的理念&#xff0c;特写这个帖子。 某思路等考通一级MSOffice&#xff0c;版本6.5。 用到的软件&#xff0c;ScanId&#xff0c;de4dot,dnSpy。 第一步&#xff1a;分析 软件启动后有在线激活提示&…

请求Controller接口结束以后怎么统一处理业务需求的三个方法参考

请求Controller接口结束以后怎么统一处理业务需求的三个方法参考 要在控制器&#xff08;Controller&#xff09;中的接口请求成功后对数据进行处理&#xff0c;可以使用 Spring MVC 中的拦截器&#xff08;Interceptors&#xff09;、AOP&#xff08;Aspect Oriented Program…

【索引优化与查询优化】

文章目录 1. 索引失效的案例1.1 最左优先1.2 主键插入顺序1.3 计算、函数、类型转换(自动或手动)导致索引失效1.4 范围条件右边的列索引失效1.5 非 条件索引失效1.6 like以通配符%开头索引失效1.7 OR 前后存在非索引的列&#xff0c;索引失效 2. 关联查询优化 1. 索引失效的案例…

FinOps和DevOps的未来会怎样?

FinOps&#xff08;或财务运营&#xff09;是一种文化实践&#xff0c;它将财务责任引入云的可变支出模型。这是一种将系统、最佳实践和文化相结合的战略方法&#xff0c;可提高组织了解云成本并做出明智决策的能力。 本质上&#xff0c;FinOps 是一个管理云运营费用&#xff…

java stream流的执行流程

Stream流是Java 8引入的一种用于处理集合数据的函数式编程概念。它提供了一种流式处理数据的方式&#xff0c;可以进行过滤、映射、排序、聚合等操作。 下面是Stream流的执行流程&#xff1a; 创建流&#xff1a;首先&#xff0c;需要有一个数据源&#xff0c;可以是集合、数组…

水面倒影可视化渲染方法

水面材质在三维可视化场景中的使用非常广泛。水面材质非常重要的一个光学特性就是反射倒影&#xff0c;有了倒影的加持能使水面更加逼真的渲染出来。本文主要讨论水面材质中倒影的渲染方法。 要有倒影&#xff0c;必须先有水面&#xff0c;第一步要做的就是确定水面所在的平面…

ChromeDriver最新版本下载与安装方法

关于ChromeDriver最新下载地址&#xff1a;https://googlechromelabs.github.io/chrome-for-testing/ 下载与安装 setp1&#xff1a;查看Chrome浏览器版本 首先&#xff0c;需要检查Chrome浏览器的版本。请按照以下步骤进行&#xff1a; 打开Chrome浏览器。 点击浏览器右上角…

状态设计模式是什么?什么是 State 状态设计模式?Python 状态设计模式示例代码

什么是 State 状态设计模式&#xff1f; 状态设计模式是一种行为型设计模式&#xff0c;它允许一个对象在其内部状态发生改变时改变其行为&#xff0c;使其看起来好像改变了其类。状态模式主要解决的问题是&#xff1a;当一个对象的行为取决于它的状态&#xff0c;并且在运行时…

【数据结构】八大排序(一)

目录 前言&#xff1a; 直接插入排序 直接插入排序代码实现 直接插入排序特性总结 希尔排序 希尔排序代码实现 希尔排序特性总结 直接选择排序 直接选择排序代码实现 直接选择排序特性总结 堆排序 堆的向下调整算法 建堆 堆排序代码实现 堆排序特性总结 前言&am…

MATLAB中字符和字符串操作

Matlab 中的字符&#xff08;char&#xff09;和字符串&#xff08;string&#xff09;_matlab char转字符串-CSDN博客 字符和字符串相互转&#xff0c;很多时候还是需要的。如下面的代码&#xff0c;需要判断一系列ASCII码&#xff0c;其实是判断字符串&#xff0c;首先fread读…

【设计模式】模板方法模式

目录 一、定义二、使用场景三、使用方法四、结构五、代码示例六、优点七、缺点八、适用场景 一、定义 1.在父类定义一个操作中的算法骨架&#xff0c;将算法的一些步骤延迟到子类中&#xff0c;使得子类可以不改变该算法结构的情况下重定义该算法的某些特定步骤 二、使用场景 …

Vue3-pnpm包管理器创建项目

一些优势&#xff1a;比同类工具快2倍左右、节省磁盘空间 官网&#xff1a;pnpm - 速度快、节省磁盘空间的软件包管理器 | pnpm中文文档 | pnpm中文网 npm升级到yarn再升级到pnpm&#xff08;速度更快&#xff09; 安装方式&#xff1a;npm install -g pnpm 创建项目&#…