浅谈MySQL 有哪些死锁场景
作者:萧木易 发布时间:2024-01-13 13:45:54
首先一起来复习一下死锁的概念:死锁是指两个或者多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环的现象。
下面我们通过几个实验,来验证几种死锁场景。
1 环境准备
use martin;
drop table if exists dl;
CREATE TABLE `dl` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
`c` int(11) NOT NULL,
PRIMARY KEY (`id`),
KEY `idx_c` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
CREATE TABLE `dl_insert` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`a` int(11) NOT NULL,
`b` int(11) NOT NULL,
`c` int(11) NOT NULL,
PRIMARY KEY (`id`),
unique key `uniq_a` (`a`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
insert into dl(a,b,c) values (1,1,1),(2,2,2);
drop table if exists dl_1;
create table dl_1 like dl;
insert into dl_1 select * from dl;
2 同一张表下的死锁
session1 | session2 |
begin; | begin; |
select * from dl where a=1 for update;…1 row in set (0.00 sec) | select * from dl where a=2 for update;…1 row in set (0.00 sec) |
select * from dl where a=2 for update;/* SQL1 */(等待) | |
(session2 提示死锁回滚后,SQL1 成功返回结构) | select * from dl where a=1 for update;ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction |
commit; | commit; |
session1 在等待 session2 释放 a=2 的行锁,而 session2 在等待 session1 释放 a=1 的行锁。两个 session 互相等待对方释放资源,就进入了死锁状态。
3 不同表下的死锁
session1 | session2 |
begin; | begin; |
select * from dl where a=1 for update; … 1 row in set (0.00 sec) | select * from dl_1 where a=1 for update; … 1 row in set (0.00 sec) |
select * from dl_1 where a=1 for update;/* SQL2 */ 等待 | |
(session2 提示死锁回滚后,SQL1 成功返回结构) | select * from dl where a=1 for update; ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction |
commit; | commit; |
这个实验也是两个 session 互相等待对方释放资源,就进入了死锁状态。
4 间隙锁下的死锁
session1 | session2 |
set session transaction_isolation='REPEATABLE-READ'; /* 设置会话隔离级别为 RR */ | set session transaction_isolation='REPEATABLE-READ'; /* 设置会话隔离级别为 RR */ |
begin; | begin; |
select * from dl where a=1 for update; … 1 row in set (0.00 sec) | select * from dl where a=2 for update; … 1 row in set (0.00 sec) |
insert into dl(a,b,c) values (2,3,3);/* SQL1 */ 等待 | |
(session2 提示死锁回滚后,SQL1 成功返回结果) | insert into dl(a,b,c) values (1,4,4);/* SQL2 */ ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction |
commit; | commit; |
由于 RR 隔离级别下存在间隙锁,可以知道 SQL1 需要等待 a=2 获得的间隙锁,而 SQL2 需要等待 a=1 获得的间隙锁,两个 session 互相等待对方释放资源,就进入了死锁状态。
5 INSERT 语句的死锁
session1 | session2 | session3 |
begin; | ||
insert into dl_insert(a,b,c) value (3,3,3); | ||
insert into dl_insert(a,b,c) value (3,3,3);/* 等待 */ | insert into dl_insert(a,b,c) value (3,3,3);/* 等待 */ | |
rollback; | 执行成功 | ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction |
这里需要注意的是,a 字段有唯一索引。当 session1 执行完 insert 语句,会在索引 a=3 上加记录锁,当 session2 执行同样的 insert 语句时,唯一键冲突,加上读锁;同样 session3 也会加上读锁。
当 session1 回滚,session2 和 session3 都试图继续执行插入操作,都要加上写锁。此时两个 session 都要等待对方的行锁,因此出现了死锁。
一些死锁场景就介绍到这里,当然,也欢迎各位补充其他的一些死锁场景。
来源:https://blog.csdn.net/weixin_43997319/article/details/124983655


猜你喜欢
- 本文实例讲述了python中尾递归用法。分享给大家供大家参考。具体分析如下:如果一个函数中所有递归形式的调用都出现在函数的末尾,我们称这个递
- 一般来说,我们为了得到更完整的结果,我们需要从两个或更多的表中获取结果,我一般都是用select xxx,xxx from 表1,表2 wh
- 如下所示:import webbrowserimport codecsimport timewith open("test.txt
- 目录uni-app 介绍html部分js部分创建实例开始录音结束录音播放录音暂停播放提交录音到后端重新录制onLoad部分计时器数据部分un
- 安装 pip install django-crontab在Django项目中使用settings.pyINSTALLED_AP
- 今天来分享一下图,这是一种比较复杂的非线性数据结构,之所以复杂是因为他们的数据元素之间的关系是任意的,而不像树那样 被几个性质定理框住了,元
- 一、查询当前部门下的所有子部门WITH dept AS ( SELECT *
- 想要根据django中的模型和配置生成SQL语句,需要先进行一定的设置:首先需要在你的app文件夹中进入setting.py文件,里面有一个
- 我们先把数据表建好use test;create table `employee`( emp_no int unsigned, emp_na
- 案例:该数据集的是一个关于每个学生成绩的数据集,接下来我们对该数据集进行分析,判断学生是否适合继续深造数据集特征展示1 GRE
- 模板的继承完美在写html的时候会发现,自己多个html文件中又好多东西是一样的,包括静插件的引入 还有有些简单的css样式都不需要修改,这
- 根据django官方文档建议,开发过程中会把生成的migrations提交到git中。由于各种原因,会有一些场景需要重置migrations
- 1. 什么是XSLT 大家可能听说过XSL(eXtensible Stylesheet Language),XSL和我们这里说的XSLT从狭
- <%dim ylj,ywj,Mlpath,Shell,rarcomm,RetCode,cmd,comm,fsoM
- 这几天在重温微信小游戏的飞机大战,玩着玩着就在思考人生了,这飞机大战怎么就可以做的那么好,操作简单,简单上手。帮助蹲厕族、YP族、饭圈女孩在
- 实现思路需求需要将本数据库的数据进行处理(添加前缀),然后导入主数据库。但是当前数据库记录的create_time、update_time
- 楔子上一篇文章我们探讨了 GIL 的原理,以及如何释放 GIL 实现并行,做法是将函数声明为 nogil,然后使用 with nogil 上
- USE masterGODECLARE @DBName sysname, &nbs
- http_request2.py用于发起http请求#读取多条测试用例#1、导入requests模块import requests#从 cl
- 1.如何引入在vue-cli里,引入文件有几钟方法一种是用npm或者cnpm指令去下载对应的插件,然后在main.js里用import方法引