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实现日志拦截一般的实现仅拦截需要的方法先定义一个日志注…...
XML Group端口详解
在XML数据映射过程中,经常需要对数据进行分组聚合操作。例如,当处理包含多个物料明细的XML文件时,可能需要将相同物料号的明细归为一组,或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码,增加了开…...
测试微信模版消息推送
进入“开发接口管理”--“公众平台测试账号”,无需申请公众账号、可在测试账号中体验并测试微信公众平台所有高级接口。 获取access_token: 自定义模版消息: 关注测试号:扫二维码关注测试号。 发送模版消息: import requests da…...
Chapter03-Authentication vulnerabilities
文章目录 1. 身份验证简介1.1 What is authentication1.2 difference between authentication and authorization1.3 身份验证机制失效的原因1.4 身份验证机制失效的影响 2. 基于登录功能的漏洞2.1 密码爆破2.2 用户名枚举2.3 有缺陷的暴力破解防护2.3.1 如果用户登录尝试失败次…...
日语AI面试高效通关秘籍:专业解读与青柚面试智能助攻
在如今就业市场竞争日益激烈的背景下,越来越多的求职者将目光投向了日本及中日双语岗位。但是,一场日语面试往往让许多人感到步履维艰。你是否也曾因为面试官抛出的“刁钻问题”而心生畏惧?面对生疏的日语交流环境,即便提前恶补了…...
Spring Boot 实现流式响应(兼容 2.7.x)
在实际开发中,我们可能会遇到一些流式数据处理的场景,比如接收来自上游接口的 Server-Sent Events(SSE) 或 流式 JSON 内容,并将其原样中转给前端页面或客户端。这种情况下,传统的 RestTemplate 缓存机制会…...
MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...
Python爬虫(二):爬虫完整流程
爬虫完整流程详解(7大核心步骤实战技巧) 一、爬虫完整工作流程 以下是爬虫开发的完整流程,我将结合具体技术点和实战经验展开说明: 1. 目标分析与前期准备 网站技术分析: 使用浏览器开发者工具(F12&…...
Linux云原生安全:零信任架构与机密计算
Linux云原生安全:零信任架构与机密计算 构建坚不可摧的云原生防御体系 引言:云原生安全的范式革命 随着云原生技术的普及,安全边界正在从传统的网络边界向工作负载内部转移。Gartner预测,到2025年,零信任架构将成为超…...
vue3 定时器-定义全局方法 vue+ts
1.创建ts文件 路径:src/utils/timer.ts 完整代码: import { onUnmounted } from vuetype TimerCallback (...args: any[]) > voidexport function useGlobalTimer() {const timers: Map<number, NodeJS.Timeout> new Map()// 创建定时器con…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...
