MySQL InnoDB死锁原因及改善建议(InnoDB Deadlocks)

news2024/9/30 1:32:14

死锁是事务型数据库中一种现象,为了在高并发环境下不出错,数据库引入了"锁"这一数据结构来控制资源的并发访问,但也会导致死锁。

目录

一、死锁概念

1.1 死锁的原因

1.2 死锁监测

二、死锁演示

2.1 死锁生成过程

2.2 死锁信息查看

三、改善建议


一、死锁概念

1.1 死锁的原因

数据库为了控制事务的并发访问,当事务要更新数据时,必须先获得数据上的"锁"。如果此时"锁"正被其他事务持有,那么就需要排队等待,当其他事务释放了锁之后(提交或回滚)。即可获取锁并对该数据进行操作。

而死锁的原因是"锁"闭环了,例如:

1. 事务A更新获取了记录1上的锁,事务B更新获取了记录2上的锁,Innodb支持行级锁,不会有任何冲突。

2. 此时如果事务A尝试获取记录2上的锁,由于其正被事务B持有,那么事务A会正常等待B释放锁。

3. 此时如果事务B又尝试去获取记录1的锁,那么它又要去等待A释放锁,两事务陷入了相互等待,即死锁。

因此死锁的原因是锁等待闭环了,实际情况可能更复杂一点,有可能是A等B,B等C,C等A,如果不加干预,那么事务有可能无限等待下去。

1.2 死锁监测

实际情况下,死锁是不会无限等待下去的,MySQL自带了死锁监控机制。死锁监控机制由参数 innodb_deadlock_detect 控制,默认就是打开的,当发现死锁时,会立刻挑选一个成本较小的事务作为“牺牲品”,回滚该事务,打破这个等待闭环。

show variables like 'innodb_deadlock_detect';

如果关闭改参数,那么MySQL将不再进行死锁监测,大家就这么一直互相等待下去,直到锁等待超时(由参数 innodb_lock_wait_timeout控制)。关闭后由死锁造成的等待超时报错是"Lock wait time out exceeded"而不是死锁的"Dead Lock Found",可能有一定的迷惑性。

二、死锁演示

下面我们通过一个示例来理解死锁,首先创建测试数据,一张test表,插入2行数据。

create table test(
id smallint not null primary key,
name varchar(32));

insert into test values(1,'Vincent');
insert into test values(2,'Victor');
commit;

2.1 死锁生成过程

准备好数据后,我们开启3个会话,会话1,2运行事务,会话3用来观察锁等待情况。

在会话1中执行:

begin;  -- 显式开启事务
update test set name='AAA' where id=1;

在会话2中执行:

begin;
update test set name='BBB' where id=2;

此时我们通过会话3来查看两个会话锁持有情况,在会话3中执行下列查询:

SELECT
engine_transaction_id,
object_name,
index_name,
lock_data,
lock_mode,
lock_status,
lock_type
FROM performance_schema.data_locks;

Innodb用的是行级锁,更新不同的记录并不冲突。我们可以看到会话1(事务ID:275981)持有记录1的锁,会话2(事务ID:275985)持有记录2的锁,状态都是GRANTED(已获取)。

此时我们再在会话1中运行下面SQL,尝试更新记录2,由于记录2的锁目前由会话2持有,那么会进入等待,会话不会返回:

update test set name='AAA' where id=2;

从会话3再次运行上面的锁查询SQL,我们看到会话1(事务ID:275981)又新增了一条锁记录,不过状态是waiting,代表其正在进行锁等待,但并没有获得(会话1等会话2条件达成了)。如果想查看它具体在等谁,可以通过performance_schema.data_lock_waits来查看,这里就不演示了。

SELECT
engine_transaction_id,
object_name,
index_name,
lock_data,
lock_mode,
lock_status,
lock_type
FROM performance_schema.data_locks;

最后一步,我们再从会话2上执行下面SQL,尝试获取会话1持有的锁,正常情况下会话2应该等会话1,而上一步中,会话1也在等待会话2,两事务陷入相互等待。MySQL会立刻探测到死锁,报错并选择一个成本小的事务回滚。

update test set name='BBB' where id=1;

本例中牺牲了会话2的事务(回滚后事务2持有的锁就全部释放了),那么会话1的事务就可以继续进行了。

2.2 死锁信息查看

在发生死锁后,也可以通过innodb 监视器(show engine innodb status;)中"LATEST DETECTED DEADLOCK"模块来查看死锁事务信息,这里显示了哪个事务持有什么锁,在等待什么,以及回滚了谁。

show engine innodb status \G;

如果经常出现死锁,你也可以打开参数innodb_print_all_deadlocks,该参数会使死锁信息打印进错误日志(由参数log_error指定)中,方便排查问题。

show variables like 'innodb_print_all_deadlocks';
set global innodb_print_all_deadlocks=1;

日志中和监视器是同样的信息,但是监视只能显示最新的死锁,打到日志中可以留存记录。

三、改善建议

通常情况下,死锁不会导致特别严重的问题,事务回滚后只要再重新提交就可以了,不会出现数据不一致的现象。但如果生产环境频繁出现死锁,那可能就会影响业务的流畅性了,这种现象通常都是应用设计不合理导致的,需要分析原因解决了。

如果经常出现死锁现象,可以尝试下列改善方法:

  • 尽量保持事务设计不要过大,更小的事务可以更快提交,及时释放资源,降低死锁概率。
  • 及时提交事务,不要让会话持有长时间未提交的事务。
  • 如果事务需要更新多张表,要保持相同的更新顺序。从案例可以看到设计不合理的应用无关事务大小,几句SQL就能导致死锁,可以将操作逻辑封装进函数或存储过程,保证按顺序获取锁。
  • 如果要使用"锁读"(select … for update / select … for share),可以尝试将隔离级别降低到 read committed.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/803291.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

cnvd水证书

日常水个证书 本人比较菜,挖cnvd总是挖不倒漏洞,只能从弱口令入手了,一般使用fofa脚本批量跑。 过程: 日常在佛法中我们总是会遇见设备弱口或系统弱口令 一般是看登录成功的特征和口令,写一个对应的弱口令检测脚本…

OceanMind海睿思获评中国信通院“内审数字化产品评测”卓越级(最高级)!

2023年7月27日,由中国内部审计协会、中国通信标准化协会指导,中国信息通信研究院主办的第二届数字化审计论坛在北京成功召开。 大会聚焦内部审计数字化领域先进实践、研究成果、行业发展举措,重磅发布了多项内部审计数字化领域的最新研究和实…

基于扩展(EKF)和无迹卡尔曼滤波(UKF)的电力系统动态状态估计(Matlab代码实现)

💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…

我的MacBook Pro:维护心得与实用技巧

文章目录 我的MacBook Pro:维护心得与实用技巧工作电脑概况:MacBook Pro 2019款 16 寸日常维护措施个人维护技巧其他建议 我的MacBook Pro:维护心得与实用技巧 无论是学习还是工作,电脑都是IT人必不可少的重要武器。一台好电脑除…

优化基于tcp,socket的ftp文件传输程序

原始程序: template_ftp_server_old.py: import socket import json import struct import os import time import pymysql.cursorssoc socket.socket(socket.AF_INET, socket.SOCK_STREAM) HOST 192.168.31.111 PORT 4101 soc.bind((HOST,PORT)) p…

03-树1 树的同构(c++)

03-树1 树的同构 给定两棵树T1和T2。如果T1可以通过若干次左右孩子互换就变成T2,则我们称两棵树是“同构”的。例如图1给出的两棵树就是同构的,因为我们把其中一棵树的结点A、B、G的左右孩子互换后,就得到另外一棵树。而图2就不是同构的。 现…

[Linux]线程基本知识

概念 进程 一个正在执行的程序,它是资源分配的最小单位 进程中的事情需要按照一定的顺序逐个进行 进程出现了很多弊端: 一是由于进程是资源拥有者,创建、撤消与切换存在较大的时空开销,因此需要引入轻型进程; 二是由于对称多…

USB3.0之设备检测

1 USB超速SerDes原理介绍 1.1 SerDes Rx.Detect SerDes Rx.Detect的原理比较简单,就是通过一个逻辑电路比较RC时间常数的大小。 当Rx不存在时,RC时间常数较小。当Rx存在时,RC时间常数较大。 下面将详细描述其原理。 Figure 1-1 USB 3.0电缆 …

App 测试工具大全,收藏这篇就够了

随着移动互联网的高速发展,App应用非常火,测试工程师也会接触到各种app应用。除了人工测试之外,也可以通过一些测试工具来提高我们的测试效率,以下对于我用过或听过的app测试工具做了一个统一整理,欢迎补充。 一、APP自…

vue的事件绑定和修饰符

😀前言 本片文章是vue系列第3篇整理了vue的事件绑定和修饰符以及注意事项和代码演示 🏠个人主页:尘觉主页 🧑个人简介:大家好,我是尘觉,希望我的文章可以帮助到大家,您的满意是我的…

Java | 继承、多态、抽象类与接口

目录 一、类的继承 二、Object类 2.1 getClass()方法 2.2 toString()方法 2.3 equals()方法 三 、对象类型的转换 3.1 向上转换 3.2 向下转型 四、使用instanceof关键字判断对象类型 五、方法的重载 六、final关键字 6.1 final变量 6.2 final方法 6.3 final类 七…

分冶算法 剑指 07 重建二叉树 排序算法:剑指45 把数组排成最小的数 10-I 斐波那契数列

来记录几个注意事项 1.vector容器里利用find&#xff08;&#xff09;函数 不同于map&#xff08;map有find方法&#xff09;&#xff0c;vector本身是没有find这一方法&#xff0c;其find是依靠algorithm来实现的。 所以要包含头文件 #include <iostream> #include <…

线程字符串传递方式

//扩展作业--参数传递 //思路: 当子线程退出的时候,pthread_exit((void *)88)--->传递给主线程 pthread_join(tid,(void *)&ret1) //函数---参数 #include <pthread.h> #include <stdio.h> #include <unistd.h> #include <stdlib.h> #include …

Y型结构,Y-shape PEG SCM,Y型聚乙二醇琥珀酰亚胺乙酸酯,具有独特的空间结构

资料编辑|陕西新研博美生物科技有限公司小编MISSwu​ 规格单位&#xff1a;g |货期&#xff1a;按照具体的库存进行提供 | 纯度&#xff1a;95% PART1----​试剂描述&#xff1a; Y-shape PEG-SCM&#xff0c;Y型结构&#xff0c;具有2个PEG链和一个琥珀酰亚胺乙酸酯基因…

三用表校准仪TD1850多用表校准系统

直流电压标准源 ( DCV ) 输出范围&#xff1a;20 mV&#xff5e;1100 V 直流电流标准源 ( DCI ) 输出范围&#xff1a;2 μA&#xff5e;22 A或33 A 交流电压标准源 ( ACV ) 输出范围&#xff1a;20 mV&#xff5e;1100 V、45 Hz&#xff5e;1100 Hz 交流电流标准源 ( ACI )…

搜索与图论(一)

一、DFS与BFS 1.1深度优先搜索(DFS) DFS不具有最短性 //排列数字问题 #include<iostream> using namespace std;const int N 10; int n; int path[N]; bool st[N];void dfs(int u) {if(u n){for(int i 0;i < n;i) printf("%d",path[i]);puts("&qu…

抖音seo源代码开发搭建--开发者概述

抖音SEO源代码开发搭建需要有一定的开发技术和经验&#xff0c;一般需要掌握以下技能&#xff1a; 掌握HTML、CSS、JavaScript等前端技术&#xff0c;能够编写静态页面和交互效果&#xff1b;了解服务器端语言如PHP、Python等&#xff0c;并能够开发后端逻辑&#xff1b;熟悉数…

Android 中 app freezer 原理详解(一):S 版本

基于版本&#xff1a;Android S 0. 前言 在之前的两篇博文《Android 中app内存回收优化(一)》和 《Android 中app内存回收优化(二)》中详细剖析了 Android 中 app 内存优化的流程。这个机制的管理通过 CachedAppOptimizer 类管理&#xff0c;为什么叫这个名字&#xff0c;而不…

【AHK】通过唤醒窗口快捷菜单调节窗口位置/打开窗口控制菜单的其他方法

需求&#xff1a;触控板使用AHK传统控制窗口位置和大小的方式不方便&#xff0c;故打算通过快捷方式唤醒窗口移动图标的方式来调节。但本人有使用utools的习惯&#xff0c;altspace打开快捷方式菜单/窗口控制菜单会冲突&#xff0c;所以一直尝试新的打开该菜单的方式——先点击…

[语义分割] DeepLab v3(Cascaded model、ASPP model、两种ASPP对比、Multi-grid、训练细节)

Rethinking Atrous Convolution for Semantic Image Segmentation 论文地址&#xff1a;Rethinking Atrous Convolution for Semantic Image SegmentationPytorch 实现代码&#xff1a;pytorch_segmentation/deeplab_v3 这是一篇 2017 年发表在CVPR上的文章。相比 DeepLab V2 有…