当前位置: 首页 > news >正文

遇到 MySQL 死锁问题如何解决?

终于来到死锁检查线程的第三步,可以解决死锁了。

作者:操盛春,爱可生技术专家,公众号『一树一溪』作者,专注于研究 MySQL 和 OceanBase 源码。

爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

本文基于 MySQL 8.0.32 源码,存储引擎为 InnoDB。

1. 选择死锁受害事务

前面介绍了死锁线程做的准备工作,以及发现死锁的过程。现在,是时候解决死锁了。

解决死锁最重要的事情,就是决定回滚死锁环中哪个事务,也就是选择哪个事务作为死锁受害事务。

选择死锁受害事务之前,还要做一件比较重要的小事,就是按照死锁环中各事务进入锁等待状态的时间从先到后进行排序。排序之后的事务,会存放到一个数组里,我们称之为死锁数组

之所以要这么做,是为了根据其它条件无法选出哪个事务作为死锁受害事务的情况下,选择最晚进入锁等待状态的事务作为死锁受害事务。

给死锁环中各事务排序之后,就可以基于死锁数组来选择死锁受害事务了。

这个过程当然又要遍历死锁数组了,同样,每次取死锁数组中的一个事务。

第 1 轮循环有点特殊,直接把取到的事务(死锁数组中第一个事务)作为候选受害事务。

第 2 轮及以后的循环,把取到的事务和上一轮循环选出来的候选受害事务进行比较,决定两者之中谁作为本轮循环的受害事务。

选择谁作为本轮循环的受害事务,这是个艰难的决定,过程如下。

第 1 步,根据两个事务的优先级,决定谁是本轮循环的受害事务。

两个事务中,如果一个是高优先级事务(优先级大于 0),一个是低优先级事务(优先级等于 0),选择低优先级事务作为本轮循环的受害事务。

如果两个事务都是高优先级事务(优先级大于 0),选择优先级更低的事务作为本轮循环的受害事务。

如果两个事务都是低优先级事务(优先级等于 0),进入第 2 步

第 2 步,根据事务是否改变(插入、更新、删除)了不支持事务的表(例如 MyISAM 表)的数据,决定谁是本轮循环的受害事务。

两个事务中,如果只有一个事务改变了不支持事务的表的数据,选择它作为本轮循环的受害事务。

如果两个事务都没有改变,或者都改变了不支持事务的表的数据,进入第 3 步

第 3 步,根据事务的回滚成本,决定谁是本轮循环的受害事务。

事务的回滚成本,由两部分相加得到:

  • 事务进入锁等待状态之前,产生的 undo 日志数量。
  • 事务进入锁等待状态之前,加表锁和行锁总共创建了几个锁结构。

如果两个事务回滚成本不同,选择成本低的那个作为本轮循环的受害事务,否则进入第 4 步

第 4 步,选择本轮循环取到的事务作为受害事务。

来到这一步,说明前三步都无法在两个事务中选出一个作为本轮循环的死锁受害事务。

这两个事务是:本轮循环取到的事务、上一轮循环选出来的受害事务。

因为死锁数组中各事务已经按照进入锁等待状态的时间先后排了序,这一步直接把本轮循环取到的事务作为本轮循环的受害事务,其实隐含了一个逻辑,就是选择两个事务中更晚进入锁等待状态的事务,作为本轮循环的受害事务。

遍历完死锁数组中所有事务之后,最终会选出一个事务作为受害事务。

2. 计算并更新事务权重

前面介绍过,在准备工作阶段,死锁线程提升阻塞事务权重时,死锁环中锁等待事务的权重,不会累加到阻塞事务的权重上,而是要等到确定死锁受害事务之后,再为死锁环中除受害之外的其它事务进行一次提升权重的操作。

现在,是时候了。

提升权重的过程,从被死锁受害事务阻塞的那个事务开始,根据死锁环中各事务的等待关系,逐个把锁等待事务的权重累加阻塞事务的权重上。

上面只介绍了提升权重操作,其实还有一个降低权重操作,就是把死锁受害事务的权重降为 0。

以上提升权重、降低权重操作的结果,都临时存放在权重数组里。

完成以上操作之后,死锁环中所有事务的权重都会更新到对应的事务对象中。

3. 记录死锁日志

如果系统变量 innodb_print_all_deadlocks 的值为 ON,死锁检查线程还会把死锁的详细信息写入 MySQL 的错误日志文件中。

示例 SQL 写入 MySQL 错误日志文件的死锁信息如下:

2024-07-07T13:00:15.602373Z 0 [Note] [MY-012468] [InnoDB] Transactions deadlock detected, dumping detailed information.
2024-07-07T13:00:15.602446Z 0 [Note] [MY-012469] [InnoDB]  *** (1) TRANSACTION:
TRANSACTION 227599, ACTIVE 21 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1192, 2 row lock(s)
MySQL thread id 8, OS thread handle 123145400471552, query id 96 localhost 127.0.0.1 root statistics
SELECT i1 FROM t1 WHERE id = 20 FOR UPDATE
2024-07-07T13:00:15.602597Z 0 [Note] [MY-012469] [InnoDB]  *** (1) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 46 n bits 80 index PRIMARY of table `test`.`t1` trx id 227599 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 00: len 4; hex 0000000a; asc     ;;1: len 6; hex 000000035958; asc     YX;;2: len 7; hex 82000000a50110; asc        ;;3: len 4; hex 80000065; asc    e;;2024-07-07T13:00:15.603277Z 0 [Note] [MY-012469] [InnoDB]  *** (1) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 46 n bits 80 index PRIMARY of table `test`.`t1` trx id 227599 lock_mode X locks rec but not gap waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 00: len 4; hex 00000014; asc     ;;1: len 6; hex 000000035958; asc     YX;;2: len 7; hex 82000000a5011d; asc        ;;3: len 4; hex 800000c9; asc     ;;2024-07-07T13:00:15.603950Z 0 [Note] [MY-012469] [InnoDB]  *** (2) TRANSACTION:
TRANSACTION 227600, ACTIVE 17 sec starting index read
mysql tables in use 1, locked 1
LOCK WAIT 3 lock struct(s), heap size 1192, 2 row lock(s)
MySQL thread id 11, OS thread handle 123145401536512, query id 97 localhost 127.0.0.1 root statistics
SELECT * FROM t1 WHERE id = 10 FOR UPDATE
2024-07-07T13:00:15.604083Z 0 [Note] [MY-012469] [InnoDB]  *** (2) HOLDS THE LOCK(S):
RECORD LOCKS space id 0 page no 46 n bits 80 index PRIMARY of table `test`.`t1` trx id 227600 lock_mode X locks rec but not gap
Record lock, heap no 3 PHYSICAL RECORD: n_fields 4; compact format; info bits 00: len 4; hex 00000014; asc     ;;1: len 6; hex 000000035958; asc     YX;;2: len 7; hex 82000000a5011d; asc        ;;3: len 4; hex 800000c9; asc     ;;2024-07-07T13:00:15.604741Z 0 [Note] [MY-012469] [InnoDB]  *** (2) WAITING FOR THIS LOCK TO BE GRANTED:
RECORD LOCKS space id 0 page no 46 n bits 80 index PRIMARY of table `test`.`t1` trx id 227600 lock_mode X locks rec but not gap waiting
Record lock, heap no 2 PHYSICAL RECORD: n_fields 4; compact format; info bits 00: len 4; hex 0000000a; asc     ;;1: len 6; hex 000000035958; asc     YX;;2: len 7; hex 82000000a50110; asc        ;;3: len 4; hex 80000065; asc    e;;2024-07-07T13:00:15.605401Z 0 [Note] [MY-012469] [InnoDB] *** WE ROLL BACK TRANSACTION (2)

前面带日期和时间的日志,只有系统变量 log_error_verbosity 的值为 3,才会记录到 MySQL 错误日志文件中。

4. 唤醒死锁受害事务

死锁环中,选择出来的受害事务,会回滚。回滚操作并不是由死锁检查线程完成,而是由事务自己完成。

要想让受害事务自己回滚,它得知道自己被选择成为死锁受害事务了,这个操作由死锁检查线程完成。

死锁检查线程会给死锁受害事务打个标志,让它在被唤醒之后,知道自己被选择成为死锁受害事务了。

死锁受害事务进入锁等待状态之前,创建了一个锁结构,这个锁结构的 type_mode 属性的第 9 位被设置为 1 了,表示这个锁结构处于锁等待状态。

现在,这个锁结构需要从事务对象的 trx_locks 链表中删除。

如果这个锁结构对应的是行锁,还需要从 rec_hash 的数组中对应的行锁结构链表中删除。

如果这个锁结构对应的是表锁,还需要从表对象的 locks 链表中删除。

然后,死锁检查线程会触发死锁受害事务的等待事件,唤醒死锁受害事务。这个等待事件,保存在死锁受害事务占用的那个 slot 对应的 srv_slot_t 对象的 event 属性中。

到这里,死锁检查线程检查并解决死锁的过程就结束了。

剩下工作,就由死锁受害事务自己完成了。

死锁受害事务要完成什么工作?

当然是回滚了。

5. 总结

死锁检查线程解决死锁的过程如下:

  • 把死锁环中各事务按照进入锁等待状态的先后顺序排好序,放到死锁数组中。
  • 遍历死锁数组,每轮循环取一个事务。
  • 第 1 轮循环取死锁数组中第 1 个事务作为候选死锁受害事务。
  • 第 2 轮及以后的循环,根据事务的优先级、是否改变了不支持事务的表的数据、事务的回滚成本,从本轮循环取到的事务,和上一轮循环选出来的死锁受害事务两者中选择一个,作为本轮循环的受害事务。
  • 最后一轮循环选出来的受害事务,就是最终的死锁受害事务,这个事务会回滚。

选出死锁受害事务之后,死锁检查线程还会根据系统变量 innodb_print_all_deadlocks 的值,决定是否记录死锁日志。

然后,会给死锁受害事务打个标记,再唤醒死锁受害事务。

更多技术文章,请访问:https://opensource.actionsky.com/

关于 SQLE

SQLE 是一款全方位的 SQL 质量管理平台,覆盖开发至生产环境的 SQL 审核和管理。支持主流的开源、商业、国产数据库,为开发和运维提供流程自动化能力,提升上线效率,提高数据质量。

✨ Github:https://github.com/actiontech/sqle

📚 文档:https://actiontech.github.io/sqle-docs/

💻 官网:https://opensource.actionsky.com/sqle/

👥 微信群:请添加小助手加入 ActionOpenSource

🔗 商业支持:https://www.actionsky.com/sqle

相关文章:

遇到 MySQL 死锁问题如何解决?

终于来到死锁检查线程的第三步,可以解决死锁了。 作者:操盛春,爱可生技术专家,公众号『一树一溪』作者,专注于研究 MySQL 和 OceanBase 源码。 爱可生开源社区出品,原创内容未经授权不得随意使用&#xff0…...

Pyinstaller打包OSError: could not get source code【终极解决】

pyinstaller 打包的时候,发现只要是torch.jit.script装饰的函数,会报以下错误: Traceback (most recent call last):File "torch/_sources.py", line 25, in get_source_lines_and_fileFile "inspect.py", line 1123, i…...

【计算机毕业设计】707高校宿舍管理系统

🙊作者简介:拥有多年开发工作经验,分享技术代码帮助学生学习,独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。🌹赠送计算机毕业设计600个选题excel文件,帮助大学选题。赠送开题报告模板&#xff…...

从C++看C#托管内存与非托管内存

进程的内存 一个exe文件,在没有运行时,其磁盘存储空间格式为函数代码段全局变量段。加载为内存后,其进程内存模式增加为函数代码段全局变量段函数调用栈堆区。我们重点讨论堆区。 托管堆与非托管堆 C# int a10这种代码申请的内存空间位于函…...

Linux进程间通信--IPC之无名管道

进程间通信(IPC,InterProcess Communication)是指在不同进程之间传播或交换信息。 IPC的方式通常有管道(包括无名管道和命名管道)、消息队列、信号量、共享存储、Socket、Streams支持不同主机上的两个进程的IPC。...

Oracle19c数据库system密码锁定

一、在oracle 19c数据库中,cdb中system用户被锁定,locked 二、所在的pdb中的system用户状态是正常的,但不可用,连接的时候提示账号已锁定 三、解决 在cdb中将system用户解锁。 alter user system account unlock;...

java之hashCode() 方法和 equals(Object obj) 方法之间的关系

1、 hashCode() 方法和 equals(Object obj) 在Java中,hashCode() 方法和 equals(Object obj) 方法之间的关系是紧密相连的,特别是在使用基于哈希的集合(如 HashSet、HashMap、HashTable 等)时。这两个方法共同决定了对象在哈希表…...

首届「中国可观测日」圆满落幕

首届中国可观测日(Observability Day)在上海圆满落幕,为监控观测领域带来了一场技术盛宴。作为技术交流的重要平台,此次活动不仅促进了观测云与亚马逊云科技之间的深化合作,更标志着双方共同推动行业发展的重要里程碑。…...

[Docker][Docker NetWork][下]详细讲解

目录 1.网络管理命令1.docker network creatre2.docker network inspect3.docker network connect4.docker network disconnect5.docker network prune6.docker network rm7.docker network ls 2.docker bridge 详解0.基本概念1.默认 bridge2.自定义 bridge3.DNS解析4.端口暴露…...

安卓系统在未来如何更好地解决隐私保护与数据安全的问题?

安卓系统可以通过以下方式更好地解决隐私保护与数据安全的问题: 强化权限控制:安卓系统可以进一步加强对应用程序权限的管理,确保用户能够清楚地知道应用程序需要哪些权限,并给予用户更多的控制权,例如允许用户选择性地…...

MySQL innodb单表上限一般多少

参考:https://www.zhihu.com/question/351797203/answer/3137174084 1.MySQL innodb单表上限为啥都说是2k万条 2.GaussDB for MySQL 为啥可以突破单表2k万的限制 要讨论这两个问题,得先明确性下实际的DB部署环境 表是索引数据是放在磁盘上的&#xf…...

更小、更安全、更透明:Google发布的Gemma推动负责任AI的进步

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…...

基于Django框架的医疗耗材管理系统的设计实现-计算机毕设定制-附项目源码(可白嫖)48999

摘 要 在目前的形势下,科技力量已成为我国的主要竞争力。而在科学技术领域,计算机的使用逐渐达到成熟,无论是从国家到企业再到家庭,计算机都发挥着其不可替代的作用,可以说计算机的可用领域遍及生活、工作的各个方面。…...

物联网协议篇(1):modbus tcp和modbusRTU的区别是什么?

Modbus TCP和Modbus RTU是Modbus协议中的两种主要变体,它们在多个方面存在显著的区别。以下是它们之间的主要区别: 1. 物理层和数据传输方式 Modbus TCP (TCP/IP): 使用以太网作为物理层,通过TCP/IP协议进行通信。数据以数据包的形式在TCP连接上传输,具有较高的通信速度和…...

JVM系列 | 对象的消亡——HotSpot的设计细节

HotSpot 的细节实现 文章目录 HotSpot 的细节实现OopMap 与 根节点枚举根节点类型及说明HotSpot中的实现 OopMap 与 安全点安全点介绍如何保证程序在安全点上? 安全区域记忆集与卡表记忆集卡表 写屏障并发的可达性分析(与用户线程)并发可达性…...

vue 运行或打包过程报错 JavaScript heap out of memory(内存溢出)

安装 increase-memory-limit npm install increase-memory-limit 运行increase-memory-limit ./node_modules/.bin/increase-memory-limit 运行后会报以下错误: "node --max-old-space-size10240" 不是内部或外部命令,也不是可运行的程序…...

git分支提交方法

先下载最新代码 改动文件覆盖 cp 文件到~/file/ git add添加文件 git commit提交本地 建立分支 git diff .c git status -uno git add git commit git checkout -b issue-lyd git push origin issue-lyd...

从微架构到向量化--CPU性能优化指北

引入 定位程序性能问题,相信大家都有很多很好的办法,比如用top/uptime观察负载和CPU使用率,用dstat/iostat观察io情况,ptrace/meminfo/vmstat观察内存、上下文切换和软硬中断等等,但是如果具体到CPU问题,我…...

声声入耳,事事如意 爱可声「如意」助听器即将上市!

如意助听器 Charm 爱可声全新系列「如意」助听器即将上市! 此次新品充分考虑了不同听损以及年龄的用户需求, 融合三大强劲性能。 1、多群体覆盖,定制个性化方案 如意助听器针对不同听损程度的听障患者设计了不同款式助听器,贴…...

生物实验室设备文件采集如何才能质量和效率双管齐下?

生物实验室的设备文件采集是实验室运营、科研活动和数据科学实践应用中不可或缺的一环。通过数据采集,实验室可以优化资源配置、提高实验结果的准确性和可靠性、支持科研水平的提升,并确保数据的安全性和可追溯性。因此,实验室应高度重视设备…...

19c补丁后oracle属主变化,导致不能识别磁盘组

补丁后服务器重启,数据库再次无法启动 ORA01017: invalid username/password; logon denied Oracle 19c 在打上 19.23 或以上补丁版本后,存在与用户组权限相关的问题。具体表现为,Oracle 实例的运行用户(oracle)和集…...

【SpringBoot】100、SpringBoot中使用自定义注解+AOP实现参数自动解密

在实际项目中,用户注册、登录、修改密码等操作,都涉及到参数传输安全问题。所以我们需要在前端对账户、密码等敏感信息加密传输,在后端接收到数据后能自动解密。 1、引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

Nginx server_name 配置说明

Nginx 是一个高性能的反向代理和负载均衡服务器&#xff0c;其核心配置之一是 server 块中的 server_name 指令。server_name 决定了 Nginx 如何根据客户端请求的 Host 头匹配对应的虚拟主机&#xff08;Virtual Host&#xff09;。 1. 简介 Nginx 使用 server_name 指令来确定…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

Mac下Android Studio扫描根目录卡死问题记录

环境信息 操作系统: macOS 15.5 (Apple M2芯片)Android Studio版本: Meerkat Feature Drop | 2024.3.2 Patch 1 (Build #AI-243.26053.27.2432.13536105, 2025年5月22日构建) 问题现象 在项目开发过程中&#xff0c;提示一个依赖外部头文件的cpp源文件需要同步&#xff0c;点…...

华硕a豆14 Air香氛版,美学与科技的馨香融合

在快节奏的现代生活中&#xff0c;我们渴望一个能激发创想、愉悦感官的工作与生活伙伴&#xff0c;它不仅是冰冷的科技工具&#xff0c;更能触动我们内心深处的细腻情感。正是在这样的期许下&#xff0c;华硕a豆14 Air香氛版翩然而至&#xff0c;它以一种前所未有的方式&#x…...

DingDing机器人群消息推送

文章目录 1 新建机器人2 API文档说明3 代码编写 1 新建机器人 点击群设置 下滑到群管理的机器人&#xff0c;点击进入 添加机器人 选择自定义Webhook服务 点击添加 设置安全设置&#xff0c;详见说明文档 成功后&#xff0c;记录Webhook 2 API文档说明 点击设置说明 查看自…...

Java后端检查空条件查询

通过抛出运行异常&#xff1a;throw new RuntimeException("请输入查询条件&#xff01;");BranchWarehouseServiceImpl.java // 查询试剂交易&#xff08;入库/出库&#xff09;记录Overridepublic List<BranchWarehouseTransactions> queryForReagent(Branch…...

Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合

无论是python&#xff0c;或者java 的大型项目中&#xff0c;都会涉及到 自身平台微服务之间的相互调用&#xff0c;以及和第三发平台的 接口对接&#xff0c;那在python 中是怎么实现的呢&#xff1f; 在 Python Web 开发中&#xff0c;FastAPI 和 Django 是两个重要但定位不…...