mysql 死锁案例及简略分析
准备数据
# 创一个测试表,存储引擎使用 innodb
create table test_lock (id int primary key auto_increment,name varchar(20),age int
)engine = innodb;insert into test_lock (name,age) values ('ionc001',10);
insert into test_lock (name,age) values ('ionc002',12);
insert into test_lock (name,age) values ('ionc003',13);
insert into test_lock (name,age) values ('ionc004',14);
insert into test_lock (name,age) values ('ionc005',15);
insert into test_lock (name,age) values ('ionc006',16);
insert into test_lock (name,age) values ('ionc007',17);
insert into test_lock (name,age) values ('ionc008',18);
insert into test_lock (name,age) values ('ionc009',19);
insert into test_lock (name,age) values ('ionc010',20);
死锁案例
- 执行事务前的数据
select * from test_lock;
| id | name | age |
|---|---|---|
| 1 | ionc001 | 10 |
| 2 | ionc002 | 12 |
| 3 | ionc003 | 13 |
| 4 | ionc004 | 14 |
| 5 | ionc005 | 15 |
| 6 | ionc006 | 16 |
| 7 | ionc007 | 17 |
| 8 | ionc008 | 18 |
| 9 | ionc009 | 19 |
| 10 | ionc010 | 20 |
- 事务执行过程
| 执行次序 | 事务 1 | 描述 | 事务 2 | 描述 |
|---|---|---|---|---|
| 1 | begin; | 事务 1 开启显式事务 | ||
| 2 | begin; | 事务 2 开启显式事务 | ||
| 3 | update test_lock set age = 100 where id = 1; | 事务 1 执行更新id = 1的记录 | ||
| 4 | update test_lock set name = ‘william’ where id = 2; | 事务 2 执行更新id = 2的记录 | ||
| 5 | update test_lock set name = ‘tx_1’ where id = 2; | 事务 1 执行更新,此时事务1会被事务2 阻塞 | ||
| 6 | update test_lock set age = 200 where id = 1; | 此条记录执行时,会报错,终止实物且整个事务回滚 | ||
| 7 | 由于事务 2 执行导致死锁,接着被 mysal检测到,终止事务 2 的执行,此时事务 1 继续执行 | |||
| commit; |
- 执行事务后的数据
| id | name | age |
|---|---|---|
| 1 | ionc001 | 100 |
| 2 | tx_1 | 12 |
| 3 | ionc003 | 13 |
| 4 | ionc004 | 14 |
| 5 | ionc005 | 15 |
| 6 | ionc006 | 16 |
| 7 | ionc007 | 17 |
| 8 | ionc008 | 18 |
| 9 | ionc009 | 19 |
| 10 | ionc010 | 20 |
show engine innodb status;
锁日志分析
=====================================
------------------------
LATEST DETECTED DEADLOCK # 上一次检测到的死锁
------------------------
2025-01-03 23:02:12 0x700010112000 # 时间
*** (1) TRANSACTION: # 事务 1
# 事务 ID,活跃时间
TRANSACTION 16535, ACTIVE 25 sec starting index read
# 表示当前事务使用了一个表,有一个表级锁(意向锁,有事务执行行级产生)
mysql tables in use 1, locked 1
# 表示表链中存在 3 个锁 (一个意向锁),堆大小,2 个行级锁,undo 日志一条
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
# 当前事务的线程id 及 执行的 SQL 语句,从语句看出来这是事务 1 的执行信息
MySQL thread id 14, OS thread handle 123145582202880, query id 2802 localhost 127.0.0.1 root updating
/* ApplicationName=DataGrip 2024.1.3 */ update test_lock set name = 'tx_1' where id = 2*** (1) HOLDS THE LOCK(S): # 持有的锁信息
# 记录锁,空间 ID,页码,事务 ID,锁模式 X lock(记录锁)且非间隙锁
RECORD LOCKS space id 368 page no 4 n bits 80 index PRIMARY of table `my_demo`.`test_lock` trx id 16535 lock_mode X locks rec but not gap
# 记录锁
Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 00: len 4; hex 80000001; asc ;; # 主键索引 11: len 6; hex 000000004097; asc @ ;; # 事务 ID 十六进制 4097 转 十进制 165352: len 7; hex 010000008f03bd; asc ;; # 回滚指针3: len 7; hex 696f6e63303031; asc ionc001;; # 本事务要更新的行记录的字段的值 ionc0014: len 4; hex 80000064; asc d;; # 本事务要更新的行记录的字段的值 十六进制 64 转 十进制 100*** (1) WAITING FOR THIS LOCK TO BE GRANTED:事务 1 等待事务 2 释放锁
RECORD LOCKS space id 368 page no 4 n bits 80 index PRIMARY of table `my_demo`.`test_lock` trx id 16535 lock_mode X locks rec but not gap waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
# 下面信息是事务 2 的执行信息0: len 4; hex 80000002; asc ;;# 主键索引 21: len 6; hex 000000004098; asc @ ;;# 事务 ID 十六进制 4098 转 十进制 165362: len 7; hex 02000000cc11ab; asc ;;# 回滚指针3: len 7; hex 77696c6c69616d; asc william;;# 本事务要更新的行记录的字段的值 william4: len 4; hex 8000000c; asc ;; # 本事务要更新的行记录的字段的值 十六进制 c 转 十进制 12*** (2) TRANSACTION:
TRANSACTION 16536, ACTIVE 19 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1136, 2 row lock(s), undo log entries 1
MySQL thread id 15, OS thread handle 123145582505984, query id 2811 localhost 127.0.0.1 root updating
/* ApplicationName=DataGrip 2024.1.3 */ update test_lock set age = 200 where id = 1*** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 368 page no 4 n bits 80 index PRIMARY of table `my_demo`.`test_lock` trx id 16536 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 5; compact format; info bits 00: len 4; hex 80000002; asc ;; # 主键索引 21: len 6; hex 000000004098; asc @ ;; # 事务 ID 十六进制 4098 转 十进制 165362: len 7; hex 02000000cc11ab; asc ;;# 回滚指针3: len 7; hex 77696c6c69616d; asc william;;# 本事务要更新的行记录的字段的值 william4: len 4; hex 8000000c; asc ;;# 本事务要更新的行记录的字段的值 十六进制 c 转 十进制 12*** (2) WAITING FOR THIS LOCK TO BE GRANTED: # 事务 2 等待事务 1 释放锁
RECORD LOCKS space id 368 page no 4 n bits 80 index PRIMARY of table `my_demo`.`test_lock` trx id 16536 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 5; compact format; info bits 0
# 下面信息是事务 1 的执行信息,0: len 4; hex 80000001; asc ;;1: len 6; hex 000000004097; asc @ ;;2: len 7; hex 010000008f03bd; asc ;;3: len 7; hex 696f6e63303031; asc ionc001;;4: len 4; hex 80000064; asc d;;*** WE ROLL BACK TRANSACTION (2) # 决定回滚事务 2
------------
TRANSACTIONS
------------
Trx id counter 16538
Purge done for trx's n:o < 16538 undo n:o < 0 state: running but idle
# ... 省略后面信息
END OF INNODB MONITOR OUTPUT
============================
开启死锁日志的持久化
- 默认情况下,上面显示引擎状态的命令,只会显示最近一次的死锁记录,可以使用下面命令查看死日志的记录参数的值,默认是关闭的
show variables like '%innodb_print_all_deadlocks%'; # off
- 开启死锁的错误日志记录
set global innodb_print_all_deadlocks = 'ON';
避免死锁的建议
避免死锁的方式,归根到底还是减少资源竞争。
- 时间上:耗时事务拆分,减少单个事务的耗时
- 空间上:事务操作的数据行尽可能的小,结果集尽可能小,减少联表操作等
- 合理使用索引,尽量把区分度高的列放到组合索引的前面(基于最左匹配原则),使得SQL 尽可能使用索引定位到最小的行(结果集),减少锁竞争。
- 调整业务逻辑 SQL 的执行顺序,把耗时操作放到后面执行,如 update语句。
- 事务拆分、避免事务执行逻辑过多,减少持锁周期。
- 在高并发的系统中不要显示加锁,能不在事务中加锁就不加锁。
相关文章:
mysql 死锁案例及简略分析
准备数据 # 创一个测试表,存储引擎使用 innodb create table test_lock (id int primary key auto_increment,name varchar(20),age int )engine innodb;insert into test_lock (name,age) values (ionc001,10); insert into test_lock (name,age) values (ionc00…...
第四届计算机、人工智能与控制工程
第四届计算机、人工智能与控制工程 The 4th International Conference on Computer, Artificial Intelligence and Control Engineering 重要信息 大会官网:www.ic-caice.net 大会时间:2025年1月10-12日 大会地点:中国合肥 (安徽大学磬苑…...
RIP配置实验
RIP配置实验 案例简介 天一公司下属三个分公司,属于不同的地区,三个公司之间用路由器连接,路由器名称分别为分别为 Router0、Router1、Router2,请把一公司的部门pc0,通过二公司路由器,连接三公司的部门pc1,公司之间通…...
C# 整型、浮点型 数值范围原理分析
总目录 前言 一、整型、浮点型 数值范围列表 二、什么是大小、范围 在上面的列表中,每个数据类型都有自己的Range (范围) 和 Size (大小)。 1. 范围 范围好理解,就是对应数据类型的数据范围,如 sbtyte 的数据范围是 -128~127,超…...
Adobe Acrobat Pro DC 2023 下载安装教程,附详细图文
简介: Adobe Acrobat Pro DC 2023 是由 Adobe 公司推出的一款全面的 PDF 编辑、查看和管理软件。这款软件无论是个人用户还是企业级用户,都可以凭借其强大的功能满足不同的需求。作为一款业内领先的 PDF 处理工具,Adobe Acrobat Pro DC 不仅…...
stable diffusion秋叶启动器安装roop插件
方法简洁明了: 第一步:下载秋叶启动器 第二步:输入网址:https://visualstudio.microsoft.com/zh-hans/downloads/,下载vs安装程序,安装开始会自动弹出如下窗口,选择2个环境:Python开…...
7-14 统计工龄
给定公司多名员工的工龄,按输入工龄顺序输出每个工龄段有多少员工。 输入格式: 给出多个整数,即每个员工的工龄,范围在[0, 50]。 输出格式: 按输入工龄顺序输出每个工龄的员工个数,格式为:“工龄:人数”。 每项占一…...
OLED的显示
一、I2C I2C时序:时钟线SCL高电平下:SDA由高变低代表启动信号,开始发送数据;SCL高电平时,数据稳定,数据可以被读走,开始进行读操作,SCL低电平时,数据发生改变࿱…...
本地测试文件解析
PostMapping("/test") public void test() throws IOException {Path csvFile Paths.get("D:\\test/27.csv");//虚拟机退出时删除临时文件csvFile.toFile().deleteOnExit();List<String> list Files.readAllLines(csvFile, Charset.forName("…...
Elasticsearch JavaRestClient版
文章目录 初始化RestHighLeveClient(必要条件)索引库操作1.创建索引库(4步)2.删除索引库(3步)3.判断索引库是否存在(3步)4.总结:四步走 文档操作1.创建文档(4…...
ubuntu 使用s3fs配置自动挂载对象存储
一、环境准备 1.有访问对象存储权限的AKSK 2.服务器、对象存储 二、实施步骤 sudo apt update sudo apt install s3fs echo "AK:SK" >/home/ubuntu/.passwd-s3fs ---位置自定义 chmod 600 /home/ubuntu/.passwd-s3fs ---权限必须要有 mkdir /data sudo s3fs …...
SQL字符串截取函数——Left()、Right()、Substring()用法详解
SQL字符串截取函数——Left()、Right()、Substring()用法详解 1. LEFT() 函数:从字符串的左侧提取指定长度的子字符串。 LEFT(string, length)string:要操作的字符串。length&#x…...
关系分类(RC)模型和关系抽取(RE)模型的区别
目标不同 关系分类模型:对给定的实体对在给定句子中预测其关系类型。两阶段(RC) 关系抽取模型:从句子中识别出所有潜在实体对,并为其预测关系类型。一阶段(NERRE) 训练/预测阶段输入输出数据不…...
什么是索引
在数据库管理系统中,索引是一种数据结构,用于快速定位数据库表中的特定记录。索引类似于一本书的目录,可以帮助数据库引擎迅速找到所需的数据,而不必扫描整个表。 类型:常见的数据库索引类型包括B树索引、哈希索引、全…...
OJ随机链表的复制题目分析
题目内容: 138. 随机链表的复制 - 力扣(LeetCode) 分析: 这道题目,第一眼感觉非常乱,这是正常的,但是我们经过仔细分析示例明白后,其实也并不是那么难。现在让我们一起来分析分析…...
UE5材质节点Distance
Distance可以计算两个物体间的距离,可以用来做过渡效果 当相机和物体距离3000的时候,就会渐渐从蓝过渡到红色,除以500是为了平滑过渡...
OSPF - SPF算法简述
SPF全称最短路径树算法,相信学过数据结构朋友应该看起来很熟悉 在一个区域内的路由器都会产生描述自己网络连接信息的LSA,包括两种信息,有路由信息和拓扑信息,简单的来说拓扑信息就是我连着谁,路由信息就是链路的地址…...
7.UE5横板2D游戏,添加分类,创建攻击,死亡逻辑,黑板实现追击玩家行为
目录 1.将变量分类 2.创建攻击 3.应用伤害逻辑 4.死亡逻辑,停止AI行为 5.AI追击玩家,使用黑板实现 1.将变量分类 2.创建攻击 创建攻击输入为鼠标左键,并绑定映射。 攻击动画,在角色状态的枚举中添加一个新的枚举 攻击输入的…...
PostgreSQL对称between比较运算
本文介绍PostgreSQL对称between比较功能:between symmetric,在动态拼接SQL时利用它可以简化判断。PostgreSQL 9.4 及以上版本支持BETWEEN SYMMETRIC操作符,MySQL、Oracle、MsSQL没有对应功能。 between 比较 PostgreSQL的between结构允许你对…...
Spring AOP面向切面编程
Spring AOP面向切面编程 面向切面编程AOP作用AOP功能AOP总结 AOP核心概念AOP的实现方式Spring 对AOP支持支持Aspect声明一个切面声明一个切入点AspectJ描述符如下AspectJ类型匹配的通配符常用的匹配规则 声明增强 用AOP实现日志拦截一般的实现仅拦截需要的方法先定义一个日志注…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
Android Bitmap治理全解析:从加载优化到泄漏防控的全生命周期管理
引言 Bitmap(位图)是Android应用内存占用的“头号杀手”。一张1080P(1920x1080)的图片以ARGB_8888格式加载时,内存占用高达8MB(192010804字节)。据统计,超过60%的应用OOM崩溃与Bitm…...
计算机基础知识解析:从应用到架构的全面拆解
目录 前言 1、 计算机的应用领域:无处不在的数字助手 2、 计算机的进化史:从算盘到量子计算 3、计算机的分类:不止 “台式机和笔记本” 4、计算机的组件:硬件与软件的协同 4.1 硬件:五大核心部件 4.2 软件&#…...
安卓基础(Java 和 Gradle 版本)
1. 设置项目的 JDK 版本 方法1:通过 Project Structure File → Project Structure... (或按 CtrlAltShiftS) 左侧选择 SDK Location 在 Gradle Settings 部分,设置 Gradle JDK 方法2:通过 Settings File → Settings... (或 CtrlAltS)…...
热烈祝贺埃文科技正式加入可信数据空间发展联盟
2025年4月29日,在福州举办的第八届数字中国建设峰会“可信数据空间分论坛”上,可信数据空间发展联盟正式宣告成立。国家数据局党组书记、局长刘烈宏出席并致辞,强调该联盟是推进全国一体化数据市场建设的关键抓手。 郑州埃文科技有限公司&am…...
基于django+vue的健身房管理系统-vue
开发语言:Python框架:djangoPython版本:python3.8数据库:mysql 5.7数据库工具:Navicat12开发软件:PyCharm 系统展示 会员信息管理 员工信息管理 会员卡类型管理 健身项目管理 会员卡管理 摘要 健身房管理…...
使用python进行图像处理—图像变换(6)
图像变换是指改变图像的几何形状或空间位置的操作。常见的几何变换包括平移、旋转、缩放、剪切(shear)以及更复杂的仿射变换和透视变换。这些变换在图像配准、图像校正、创建特效等场景中非常有用。 6.1仿射变换(Affine Transformation) 仿射变换是一种…...
视觉slam--框架
视觉里程计的框架 传感器 VO--front end VO的缺点 后端--back end 后端对什么数据进行优化 利用什么数据进行优化的 后端是怎么进行优化的 回环检测 建图 建图是指构建地图的过程。 构建的地图是点云地图还是什么信息的地图? 建图并没有一个固定的形式和算法…...
鸿蒙APP测试实战:从HDC命令到专项测试
普通APP的测试与鸿蒙APP的测试有一些共同的特征,但是也有一些区别,其中共同特征是,它们都可以通过cmd的命令提示符工具来进行app的性能测试。 其中区别主要是,对于稳定性测试的命令的区别,性能指标获取方式的命令的区…...
JVM——对象模型:JVM对象的内部机制和存在方式是怎样的?
引入 在Java的编程宇宙中,“Everything is object”是最核心的哲学纲领。当我们写下new Book()这样简单的代码时,JVM正在幕后构建一个复杂而精妙的“数据实体”——对象。这个看似普通的对象,实则是JVM内存管理、类型系统和多态机制的基石。…...
