MySQL死锁详细介绍

首先死锁产生的原因:两个及以上事务争夺资源导致互相等待造成的
比如事务A先修改id为1的数据再去修改id为2的数据,事务B先修改id为2的数据再去修改id为1的数据,因为事务A先拿到id1的锁再去拿id2的锁,而事务B先拿到id2的锁又去拿id1的锁,此时死锁就产生了

下面我们来演示一下(以下所有操作都是在MySQL5.7.43下进行,操作工具为Navicat)

先建一张表

CREATE TABLE `t_test` (`id` int(11) NOT NULL AUTO_INCREMENT,`name` varchar(32) DEFAULT NULL,`age` int(11) DEFAULT NULL,`create_time` datetime DEFAULT CURRENT_TIMESTAMP,`update_time` datetime DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;

往里面加两条数据

在这里插入图片描述

然后我们打开两个查询窗口
窗口一

START TRANSACTION; # 开启事务UPDATE t_test SET age = 21 WHERE id = 1UPDATE t_test SET age = 31 WHERE id = 2COMMIT; # 提交事务ROLLBACK; # 回滚

在这里插入图片描述

窗口二

START TRANSACTION; # 开启事务UPDATE t_test SET age = 32 WHERE id = 2UPDATE t_test SET age = 22 WHERE id = 1COMMIT; # 提交事务ROLLBACK; # 回滚

在这里插入图片描述

我们先去窗口一启动事务(执行第一行)

在这里插入图片描述

然后去窗口二开启事务(执行第一行)

在这里插入图片描述

回到窗口一,执行修改id1的数据

在这里插入图片描述

刷新表格可以看到因为开启了事务数据没有更新

在这里插入图片描述

再去窗口二,执行修改id2的数据

在这里插入图片描述

一样的刷新表格,数据此时没有更新进来

在这里插入图片描述

回到窗口一,执行修改id2的数据
可以发现窗口上显示正在处理,下面信息里面也显示UPDATE t_test SET age = 31 WHERE id = 2,但是并没有显示执行完成,因为在等待id2的锁,而此时id2的锁在窗口二那里

在这里插入图片描述

这个时候我们再去窗口二,执行修改id1的数据
可以看到已经提示死锁Deadlock found when trying to get lock; try restarting transaction

在这里插入图片描述

此时我们提交窗口二的事务

在这里插入图片描述

刷新数据,因为已经异常了数据不会更新的

在这里插入图片描述

我们再回到窗口一,提交事务

在这里插入图片描述

刷新数据,显示数据提交成功

在这里插入图片描述

看到没有,这就是死锁产生的原因,两个事务按照不同的顺序去拿锁产生了冲突

那如果两个事务按相同的顺序拿锁会死锁吗?我们改一下两个窗口的SQL执行顺序

窗口一

START TRANSACTION; # 开启事务UPDATE t_test SET age = 40 WHERE id = 1UPDATE t_test SET age = 50 WHERE id = 2COMMIT; # 提交事务ROLLBACK; # 回滚

在这里插入图片描述

窗口二

START TRANSACTION; # 开启事务UPDATE t_test SET age = 42 WHERE id = 1UPDATE t_test SET age = 52 WHERE id = 2COMMIT; # 提交事务ROLLBACK; # 回滚

在这里插入图片描述

开启窗口一的事务

在这里插入图片描述

开启窗口二的事务

在这里插入图片描述

去窗口一修改id1的数据

在这里插入图片描述

刷新数据,数据未更新

在这里插入图片描述

去窗口二执行修改id1的数据
此时窗口处于等待状态,因为id1的锁在窗口一那里

在这里插入图片描述

去窗口一执行修改id2的数据

在这里插入图片描述

刷新数据未更新

在这里插入图片描述

去窗口二执行修改id2的数据
发现没有反应,下面显示的还是UPDATE t_test SET age = 42 WHERE id = 1执行中,因为上面一个id1还没拿到锁,所以此时无法执行id2的修改,但是可以发现不会报错,只是处于等待获取锁的状态

在这里插入图片描述

提交窗口一的事务

在这里插入图片描述

刷新数据,数据更新成功

在这里插入图片描述

回到窗口二
发现id1执行了,因为窗口一提交了事务,所以窗口二拿到了锁

在这里插入图片描述

继续执行修改id2数据

在这里插入图片描述

刷新数据未更新,因为窗口二的事务未提交

在这里插入图片描述

提交窗口二的事务

在这里插入图片描述

刷新数据,数据更新成功

在这里插入图片描述

到这里可以发现,如果两个事务按照相同的顺序获取锁是不会产生死锁的,但是会出现如果一个事务一直不提交导致另一个事务一直等待锁的情况,最后会出现等待超时异常问题

接着我要说的是正常的查询语句是不涉及到死锁问题的,因为查询用的是S锁也就是共享锁或读锁,当然你要是在后面加 FOR UPDATE(悲观锁) 当我没说

这里我们可以验证一下查询语句是不是会导致死锁的问题

我在窗口二加了一条查询语句

START TRANSACTION; # 开启事务SELECT * FROM t_test WHERE id = 1UPDATE t_test SET age = 42 WHERE id = 1UPDATE t_test SET age = 52 WHERE id = 2COMMIT; # 提交事务ROLLBACK; # 回滚

在这里插入图片描述

我们还是先开启窗口一和窗口二的事务

在这里插入图片描述

在这里插入图片描述

执行窗口一修改id1的数据,此时窗口一拿到了id1的锁

在这里插入图片描述

我们再去窗口二执行查询语句
可以看到不受影响能查询出数据

在这里插入图片描述

在继续执行窗口二修改id1数据
可以看到此时是等待获取锁的状态

在这里插入图片描述

为了证明查询语句也不影响修改语句,我们继续
之前的运行直接回滚或提交都行

在这里插入图片描述

在这里插入图片描述

还是先开启两个窗口的事务

在这里插入图片描述
在这里插入图片描述

这次我们先执行窗口二的查询
可以看到拿到结果了

在这里插入图片描述

再去窗口一执行修改id1的数据
可以看到能到拿到锁,说明窗口二的查询语句不会影响到窗口一修改语句获取锁

在这里插入图片描述

可以得出一个结论,死锁不会发生在查询语句上,查询语句不会影响其它事务获取锁的操作,注意这里的查询语句不带 FOR UPDATE
还有就是删除也是需要获取锁的,跟修改一下,这里就不演示了

这里还有一点很重要的地方需要注意,那就是表锁和行锁的问题,就是MySQL在什么情况下是表锁,什么情况下是行锁

重点要注意的就是索引的问题,如果查询条件没有命中索引,那么就是表锁

我们调整一下窗口一的语句

START TRANSACTION; # 开启事务# DELETE FROM t_test WHERE id = 1UPDATE t_test SET age = 42 WHERE name = 'Z3'# UPDATE t_test SET age = 40 WHERE id = 1# UPDATE t_test SET age = 50 WHERE id = 2COMMIT; # 提交事务ROLLBACK; # 回滚

在这里插入图片描述

再调整一下窗口二的语句

START TRANSACTION; # 开启事务# SELECT * FROM t_test WHERE id = 1# UPDATE t_test SET age = 42 WHERE id = 1UPDATE t_test SET age = 52 WHERE id = 2COMMIT; # 提交事务ROLLBACK; # 回滚

在这里插入图片描述

窗口一修改的是id1 name='Z3’的,窗口二修改的是id2的

在这里插入图片描述

还是先开启两个窗口的事务

在这里插入图片描述
在这里插入图片描述
我们先去执行窗口一修改name为Z3的数据

在这里插入图片描述

再去窗口二执行修改id1的数据
发现窗口二处在等待获取锁的状态,但是窗口一修改的是id1的数据,窗口二修改的是id2的数据,这就说明窗口一其实锁的是整张表

在这里插入图片描述

全部回滚一下

在这里插入图片描述
在这里插入图片描述

我们再重新开启两个窗口的事务

在这里插入图片描述
在这里插入图片描述

这次我们先执行窗口二修改id2的数据

在这里插入图片描述

再去窗口一执行修改name Z3的数据
发现窗口一处在等待获取锁的状态,因为id2的锁在窗口二那里,这也证明了窗口一需要锁全表

在这里插入图片描述

为了证明这个锁表是索引导致的,我们去给name加上索引
这里加的就是NORMAL普通索引,记得保存

在这里插入图片描述

回滚重新开启两个窗口的事务

在这里插入图片描述
在这里插入图片描述

一样的我们先执行窗口一修改name为Z3的数据

在这里插入图片描述

再去窗口二执行修改id2的数据
可以看到没有进入等待获取锁状态,它拿到锁了,说明这次窗口一没有锁表,因为我们给name字段加了索引,所以才没有锁表

在这里插入图片描述

这里告诫大家,经常用来做查询条件的字段一定要建索引!!!索引很重要!!!不然一不小心就会锁表!!!

最后再讲一点,就是修改 name=Z3 和修改id1的锁有没有区别的问题

我们先改一下窗口二的语句

START TRANSACTION; # 开启事务# SELECT * FROM t_test WHERE id = 1UPDATE t_test SET age = 42 WHERE id = 1# UPDATE t_test SET age = 52 WHERE id = 2COMMIT; # 提交事务ROLLBACK; # 回滚

在这里插入图片描述

重新开启两个窗口的事务

在这里插入图片描述
在这里插入图片描述
我们先去窗口一执行修改name=Z3的语句
可以看到已经拿到锁了

在这里插入图片描述

再去窗口二执行修改id1的数据
可以看到处在获取锁的状态,说明nameZ3和id1其实是同一个锁
这里深处逻辑我就不研究了,我猜的是MySQL所有的行锁都是用主键ID锁的,即使你用其它索引查询的,最终还是回表查询拿到这条数据的主键id,然后再根据主键id锁住这行

在这里插入图片描述

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

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

相关文章

“成像光谱遥感技术中的AI革命:ChatGPT应用指

遥感技术主要通过卫星和飞机从远处观察和测量我们的环境,是理解和监测地球物理、化学和生物系统的基石。ChatGPT是由OpenAI开发的最先进的语言模型,在理解和生成人类语言方面表现出了非凡的能力。本文重点介绍ChatGPT在遥感中的应用,人工智能…

【Algorithms 4】算法(第4版)学习笔记 16 - 4.2 有向图

文章目录 前言参考目录学习笔记1:介绍1.1:有向图简介1.2:应用举例1.3:相关问题2:有向图 API2.1:有向图表示2.1.1:邻接表数组 Adjacency-list2.1.2:Java 实现:邻接表数组2…

Sftp服务器搭建(linux)

Sftp服务器搭建(linux) 一、基本工作原理 FTP的基本工作原理如下: 1)建立连接:客户端与服务器之间通过TCP/IP建立连接。默认情况下,FTP使用端口号21作为控制连接的端口。​​​​​​​ 2)身…

基于AI软件平台 HEGERLS智能托盘四向车机器人物流仓储解决方案持续升级

随着各大中小型企业对仓储需求的日趋复杂,柔性、离散的物流子系统也不断涌现,各种多类型的智能移动机器人、自动化仓储装备大量陆续的应用于物流行业中,但仅仅依靠传统的物流技术和单点的智能化设备,已经无法更有效的应对这些挑战…

Office 2007软件安装教程(附软件下载地址)

软件简介: 软件【下载地址】获取方式见文末。注:推荐使用,更贴合此安装方法! 微软Office 2007是一款具有重大创新与革命性的办公软件套件。它引入了全新设计的用户界面,提供稳定安全的文件格式,并实现了无…

数据结构 - 堆(优先队列)+ 堆的应用 + 堆练习

文章目录 前言堆一、什么是堆二、堆又分为大根堆和小根堆三、由于堆的逻辑结构被看成完全二叉树,那么我们先来了解一下完全二叉树。四、堆使用数组还是链表储存数据呢?五、数组构建二叉树和父子节点之间的定位六、堆进行的操作七、实现小根堆1、堆的初始…

vue2【详解】生命周期(含父子组件的生命周期顺序)

1——beforeCreate:在内存中创建出vue实例,数据观测 (data observer) 和 event/watcher 事件配置还没调用(data 和 methods 属性还没初始化) 【执行数据观测 (data observer) 和 event/watcher 事件配置】 2——created&#xf…

指纹加密U盘/指纹KEY方案——采用金融级安全芯片 ACH512

方案概述 指纹加密U盘解决方案可实现指纹算法处理、数据安全加密、数据高速存取(EMMC/TF卡/NandFlash),可有效保护用户数据安全。 方案特点 • 采用金融级安全芯片 ACH512 • 存储介质:EMMC、TF卡、NandFlash • 支持全系列国密…

解决白屏问题:让你的网站重焕生机

🤍 前端开发工程师、技术日更博主、已过CET6 🍨 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 🕠 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 🍚 蓝桥云课签约作者、上架课程《Vue.js 和 E…

软件测试 —— 如何测试图片上传功能?

作为一名专业的软件测试人员,测试图片上传功能是一个重要的任务,以下是一些测试该功能的常用方法: 1. 上传功能测试:确保图片上传功能正常工作,包括选择图片文件、点击上传按钮、上传进度显示、上传成功/失败的提示等。…

JavaWeb03-HTTP协议,Tomcat,Servlet

目录 一、HTTP协议 1.概述 2.特点 3.请求数据格式 (1)请求行 (2)请求头 (3)请求体 (4)常见请求头 (5)GET和POST请求区别 4.响应数据格式 &#xf…

gRPC-第二代rpc服务

在如今云原生技术的大环境下,rpc服务作为最重要的互联网技术,蓬勃发展,诞生了许多知名基于rpc协议的框架,其中就有本文的主角gRPC技术。 一款高性能、开源的通用rpc框架 作者作为一名在JD实习的Cpper,经过一段时间的学…

Flask python开发篇: 写一个简单的接口

第一步:新建flask项目 参考使用pycharm新建一个项目 打开pycharm,根据下面图中箭头顺序,新建一个flask的项目; 第二步:运行项目, 安装成功以后,会有个app.py文件,打开以后&#…

qt一个项目有且只有有一个maindow,其他小窗口用QWidget,QDialog是带有yes和no的QWidget

QMaindow QWidget QDialog区别很大 我想要在生成一个小窗口,结果选择基类为maindow,应该是QWidget 然后就出现奇奇怪怪的问题 QMaindow和QWidget不能乱选择,而且各自QPaintEvent也有很多区别 以下就是错误: 我继承maindow的基类…

云服务器实例重启后,各个微服务的接口(涉及mysql操作的)都用不了了

问题描述: 云服务器被黑客植入挖矿。重启云服务器实例后得到解决,接着把docker(zookeeper、redis啥的)还有后端jar包啥的都重启了,然后发现后端接口访问不了,只有不涉及数据库操作的接口正常访问&#xff…

【毕业】 医药药店销售管理系统

1、引言 设计结课作业,课程设计无处下手,网页要求的总数量太多?没有合适的模板?数据库,java,python,vue,html作业复杂工程量过大?毕设毫无头绪等等一系列问题。你想要解决的问题&am…

自动驾驶革命:解密端到端背后的数据、算力和AI奇迹

作者 |毫末智行数据智能科学家 贺翔 编辑 |祥威 最近,特斯拉FSD V12的发布引发了业界对端到端自动驾驶的热议,业界纷纷猜测FSD V12的强大能力是如何训练出来的。从马斯克的测试视频可以大致归纳一下FSD V12系统的一些核心特征: 训练数据&am…

防御保护第七次作业-IPSEC VPPN实验

(场景选用点到点,配置好FW1的出接口地址和对端FW3的接口地址,认证方式选用预共享密钥,身份认证选用IP地址) 1、FW1 IP Sec策略配置 IKE参数配置: IP Sec参数: FW2配置: 加密数据流配…

【附教程】2024,人工智能+AI绘画,看这里就够了~14款主流图像生成软件工具总有一个适合你

AI绘画技术通过深度学习和处理海量图像数据,能够迅速将文字描述转化为富有创意和艺术性的画作。这一技术不仅极大地提升了艺术家的创作效率和作品质量,还为他们提供了全新的灵感来源和创作方式,推动了艺术领域的创新与发展。 同时&#xff0…

Redis持久化:RDB和AOF

RDB(Redis DataBase) AOF(Append Only File) AOF重写 RDB AOF 混合持久化 开启 RDB 持久化: RDB 是默认启用的,但你可以检查并设置相关参数以满足你的需求,例如更改保存间隔时间、数据库大…