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实现日志拦截一般的实现仅拦截需要的方法先定义一个日志注…...
Linux应用开发之网络套接字编程(实例篇)
服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...
(十)学生端搭建
本次旨在将之前的已完成的部分功能进行拼装到学生端,同时完善学生端的构建。本次工作主要包括: 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...
AI Agent与Agentic AI:原理、应用、挑战与未来展望
文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例:使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例:使用OpenAI GPT-3进…...
华硕a豆14 Air香氛版,美学与科技的馨香融合
在快节奏的现代生活中,我们渴望一个能激发创想、愉悦感官的工作与生活伙伴,它不仅是冰冷的科技工具,更能触动我们内心深处的细腻情感。正是在这样的期许下,华硕a豆14 Air香氛版翩然而至,它以一种前所未有的方式&#x…...
SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题
分区配置 (ptab.json) img 属性介绍: img 属性指定分区存放的 image 名称,指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件,则以 proj_name:binary_name 格式指定文件名, proj_name 为工程 名&…...
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join
纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...
RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...
GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
c++第七天 继承与派生2
这一篇文章主要内容是 派生类构造函数与析构函数 在派生类中重写基类成员 以及多继承 第一部分:派生类构造函数与析构函数 当创建一个派生类对象时,基类成员是如何初始化的? 1.当派生类对象创建的时候,基类成员的初始化顺序 …...
django blank 与 null的区别
1.blank blank控制表单验证时是否允许字段为空 2.null null控制数据库层面是否为空 但是,要注意以下几点: Django的表单验证与null无关:null参数控制的是数据库层面字段是否可以为NULL,而blank参数控制的是Django表单验证时字…...
