mysql-死锁

news2024/9/20 20:37:30

文章目录

  • 1、概念
    • 1.1、创建表 account
    • 1.2、id 自动创建 主键索引 primary
    • 1.3、name 没有创建索引
  • 2、产生死锁的必要条件
    • 2.1、此时 name 没有创建 索引
  • 3、如何处理死锁
    • 3.1、方式1:等待,直到超时(innodb_lock_wait_timeout=50s)
    • 3.2、方式2:使用 死锁 检测进行死锁处理
    • 3.3、如何解决?
    • 3.4、进一步的思路:
  • 4、如何避免死锁

1、概念

两个事务都持有对方需要的锁,并且在等待对方释放,并且双方都不会释放自己的锁。
举例1:

事务1事务2
1start transaction;
start transaction;
2update account set money=100 where id =1;
3update account set money=100 where id = 2;
4update account set money=200 where id=2;
5update account set money=200 where id =1;

1.1、创建表 account

drop table if exists account;
create table account(
id int primary key AUTO_INCREMENT comment 'ID',
name varchar(10) comment '姓名',
money double(10,2) comment '余额'
) comment '账户表';
insert into account(name, money) VALUES ('A',2000), ('B',2000);

1.2、id 自动创建 主键索引 primary

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

mysql> select * from account;
+----+------+--------+
| id | name | money  |
+----+------+--------+
|  1 | A   | 100.00 |
|  2 | B   | 200.00 |
+----+------+--------+
2 rows in set (0.00 sec)

举例2:

用户A给用户B转账100,在此同时,用户B也给用户A转账100。这个过程,可能导致死锁

事务1事务2
1start transaction;
start transaction;
2update account set money= money - 100 where name = ‘A’;
3update account set money= money - 100 where name = ‘B’;
4update account set money= money + 100 where name = ‘B’;
5update account set money= money + 100 where name = ‘A’;
mysql> select * from account;
+----+------+---------+
| id | name | money   |
+----+------+---------+
|  1 | A    | 2000.00 |
|  2 | B    | 2000.00 |
+----+------+---------+
2 rows in set (0.00 sec)

1.3、name 没有创建索引

在这里插入图片描述
因为name没有创建索引,所以此时行锁升级为表锁,此时 account表 被锁定,所以 update account set money= money - 100 where name = ‘B’;和update account set money= money + 100 where name = ‘A’;执行不成功,发生阻塞。

mysql> select * from account;
+----+------+---------+
| id | name | money   |
+----+------+---------+
|  1 | A    | 1900.00 |
|  2 | B    | 2100.00 |
+----+------+---------+
2 rows in set (0.00 sec)

在这里插入图片描述

2、产生死锁的必要条件

  1. 两个或者两个以上事务
  2. 每个事务都已经持有锁并且申请新的锁
  3. 锁资源同时只能被同一个事务持有或者不兼容
  4. 事务之间因为持有锁和申请锁导致彼此循环等待

死锁的关键在于:两个(或以上)的Session加锁的顺序不一致。

事务1事务2
1start transaction;
start transaction;
2update account set money = money - 100 where name = ‘A’;
3update account set money = money + 100 where name = ‘A’;
4update account set money = money + 100 where name = ‘B’;
5update account set money = money - 100 where name = ‘B’;

此时不会发生死锁。

mysql> select * from account;
+----+------+---------+
| id | name | money   |
+----+------+---------+
|  1 | A    | 2000.00 |
|  2 | B    | 2000.00 |
+----+------+---------+
2 rows in set (0.00 sec)

2.1、此时 name 没有创建 索引

因为name没有创建索引,所以此时行锁升级为表锁,此时 account表 被锁定,所以 update account set money = money + 100 where name = ‘A’;和update account set money = money - 100 where name = ‘B’;执行不成功,发生阻塞。
在这里插入图片描述

mysql> select * from account;
+----+------+---------+
| id | name | money   |
+----+------+---------+
|  1 | A    | 1900.00 |
|  2 | B    | 2100.00 |
+----+------+---------+
2 rows in set (0.00 sec)

3、如何处理死锁

3.1、方式1:等待,直到超时(innodb_lock_wait_timeout=50s)

mysql> show variables like 'innodb_lock_wait_timeout';
+--------------------------+-------+
| Variable_name            | Value |
+--------------------------+-------+
| innodb_lock_wait_timeout | 50    |
+--------------------------+-------+
1 row in set (0.04 sec)

等待,直到超时(innodb_lock_wait_timeout=50s)。
即当两个事务互相等待时,当一个事务等待时间超过设置的阈值时,就将其 回滚,另外事务继续进行。
这种方法简单有效,在innodb中,参数 innodb_lock_wait_timeout 用来设置超时时间。

缺点:对于在线服务来说,这个等待时间往往是无法接受的。
那将此值修改短一些,比如 1s,0.1s 是否合适? 不合适,容易误伤到普通的锁等待。

3.2、方式2:使用 死锁 检测进行死锁处理

方式1 检测死锁太过被动,innodb还提供了 wait-for graph 算法 来主动进行死锁检测,每次加锁请求无法立即满足需要并进入等待时,wait-for graph 算法 都会被触发。

这是一种较为 主动的死锁检测机制 ,要求数据库保存 锁的信息链表事务等待链表 两部分信息。
在这里插入图片描述
基于这两个信息,可以绘制 wait-for graph (等待图)
在这里插入图片描述

死锁检测的原理 是构建一个以事务为顶点、锁 为边的有向图,判断有向图是否存在环,存在既有死锁。

一旦检测到回路、有死锁,这时候 InnoDB 存储引擎 会选择 回滚undo量最小的事务,让其他事务继续执行(innodb_deadlock_detect=on 表示开启这个逻辑)。

缺点:每个新的被阻塞的线程,都要判断是不是由于自己的加入导致了死锁,这个操作时间复杂度是O(n)。如果100个并发线程同时更新同一行,意味着要检测100*100=1万次,1万个线程就会有1千万次检测。

3.3、如何解决?

  • 方式1:关闭死锁检测,但意味着可能会出现大量的超时,会导致业务有损。
  • 方式2:控制并发访问的数量。比如在中间件中实现对于相同行的更新,在进入引擎之前排队,这样在InnoDB内部就不会有大量的死锁检测工作。

3.4、进一步的思路:

可以考虑通过将一行改成逻辑上的多行来减少 锁冲突。比如,连锁超市账户总额的记录,可以考虑放到多条记录上。账户总额等于这多个记录的值的总和。

4、如何避免死锁

  • 合理设计索引,使业务SQL尽可能通过索引定位更少的行,减少锁竞争。
  • 调整业务逻辑SQL执行顺序,避免 update/delete 长时间持有锁的 SQL 在事务前面。
  • 避免大事务,尽量将大事务拆成多个小事务来处理,小事务缩短锁定资源的时间,发生锁冲突的几率也更少。
  • 在并发比较高的系统中,不要显示加锁,特别是是在事务里显示加锁。比如 select … for update 语句,如果是在事务运行了 start transaction 或设置了 autocommit 等于 0,那么就会锁定所查找到的记录。
  • 降低隔离级别。如果业务允许,将隔离级别调低也是较好的选择,比如将隔离级别从 RR 调整为 RC,可以避免掉很多因为 gap 锁造成的死锁。

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

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

相关文章

软件测试分类篇(上)

目录 引言: 一、为什么要对软件测试进行分类 二、按照测试目标分类 1. 界面测试 2. 功能测试 3. 性能测试 4. 可靠性测试 5. 安全性测试 6. 易用性测试 三、按照执行方式分类 1. 静态测试 2. 动态测试 四、按照测试方法分类 1. 白盒测试 2. 黑盒测试 …

继承常见问题

问题一: 下面关于继承说法不正确的是( ) A.继承可以使用现有类的所有功能,并在无需重新编写原来类的情况下对这些功能进行扩展 B.继承体系中子类必须要体现出与基类的不同 C.子类对象一定比基类对象大 D.继承呈现了面相对象程序设…

关于若尔当矩阵中过渡矩阵的求法

关于若尔当矩阵中过渡矩阵的求法 豆瓜爱数学 ​关注 桜井雪子 等 114 人赞同了该文章 本文主要介绍考研中常考的另一类问题,当我们确认一个Jordan标准形时,对于过渡矩阵如何确定?这个常常是我们复习过程中容易忽略的一部分内容,…

【QT基础】创建项目项目代码解释

目录 前言一,使⽤Qt Creator 新建项目1. 新建项目2. 选择项⽬模板3. 选择项⽬路径4. 选择构建系统5. 填写类信息设置界⾯6. 选择语⾔和翻译⽂件7. 选择Qt套件8. 选择版本控制系统9. 最终效果 二,项目代码说明1. main.cpp文件2. Widget.h文件3. Widget.cp…

AI大模型之旅--milvus向量库安装

milvus-向量索引库 milvus的官方文档中看到最新版本的部署方式 :https://milvus.io/docs/install_standalone-docker.md 部署 curl -sfL https://raw.githubusercontent.com/milvus-io/milvus/master/scripts/standalone_embed.sh -o standalone_embed.sh 如果下载不下来&a…

AI浪潮新崛起:借助AI+实景/视频直播创新魅力,开启无人自动直播新时代!

AI浪潮新崛起:借助AI实景/视频直播创新魅力,开启无人自动直播新时代! 在科技日新月异的今天,人工智能(AI)已不再仅仅是科幻电影中的桥段,它正以不可阻挡之势渗透到我们生活的方方面面&#xff…

【笔记】自动驾驶预测与决策规划_Part3_路径与轨迹规划

文章目录 0. 前言1. 基于搜索的路径规划1.1 A* 算法1.2 Hybrid A* 算法 2. 基于采样的路径规划2.1 Frent Frame方法2.2 Cartesian →Frent 1D ( x , y ) (x, y) (x,y) —> ( s , l ) (s, l) (s,l)2.3 Cartesian →Frent 3D2.4 贝尔曼Bellman最优性原理2.5 高速轨迹采样——…

糟糕~!注册中心是什么!

1. 什么是注册中心 注册中心是服务实例信息的存储仓库,也是服务提供者和服务消费者进行交互的桥梁。它主要提供了服务注册和服务发现这两大核心功能。 我我们看这张服务注册流程图就知道,对于注册中心而言,服务的提供者和消费者都相当于是它…

Jboss CVE-2017-7504 靶场攻略

漏洞介绍 JBoss AS 4.x及之前版本中,JbossMQ实现过程的JMS over HTTP Invocation Layer的 HTTPServerILServlet.java⽂件存在反序列化漏洞,远程攻击者可借助特制的序列化数据利⽤该漏洞执⾏ 任意代码执⾏ 影响范围 JBoss 4.x 以及之前的所有版本 环…

2024 中秋盛景:数据璀璨,文旅辉煌

2024 年的中秋假期,文旅市场热闹非凡。看这一组组令人惊叹的数据,感受中秋旅游的火爆魅力。国内出游人次高达 1.07 亿,相比 2019 年同期增长了 6.3%,这意味着无数人踏上旅途,追寻着心中的诗和远方。国内游客出游总花费…

揭开 Vue 3 中大量使用 ref 的隐藏危机

在 Vue 3 中,ref 是用来创建响应式的引用,它能够追踪和管理单一的变量或对象。当代码中大量使用 ref 时,虽然可以实现对各个状态或数据的精细控制,但也会带来一些问题和潜在影响。 1. 大量使用 ref 带来的问题 1、代码冗长与维护…

超强提分神器:大模型+RAG!新SOTA性能提升50%+,实现计算资源动态分配

现在的大模型因为“幻觉”问题,已经离不开“外挂”检索增强生成RAG了,而且很多大模型应用几乎完全基于RAG构建,可以说决定了大模型生成的天花板。 这是因为RAG可以将外部数据检索集成到生成过程中,不仅确保了大模型生成的内容具有…

微服务保护详细笔记(一):雪崩问题--Sentinel

目录 1.雪崩问题 1.1.雪崩问题产生原因: 1.2.雪崩问题解决方案 1.2.1.请求限流 1.1.2.线程隔离 1.1.3.服务熔断 1.3.微服务保护技术对比 1.4.Sentinel 1.4.1.介绍与安装 1.4.2.微服务整合 1.雪崩问题 1.1.雪崩问题产生原因: 比如查询购物车的…

【省时省力】告别 Node.js 安装配置的繁琐!国内镜像源加速,版本切换轻松搞定

前言 最近电脑开发环境又意外出现了异常,每次更新系统都是冒着很大的风险,这次最直接的影响就是一些基于nodejs的前端项目. 不同项目的版本环境要求不一致,最新的nodejs并不总是满足项目要求,因此为了重新部署自己开发的以及别人开发的项目,需要根据项目随时切换到相应的版本.…

git使用“保姆级”教程2——初始化及工作机制解释

1、设置用户签名 解释: 签名的作用就是用来:标识用户,以区分不同的开发人员简单来说:用来标识"你是谁",在提交代码时,会显示提交代码的是谁,把设置的信息一起提交上去 设置&#xff…

sqoop的安装与简单使用

文章目录 一、安装1、上传,解压,重命名2、修改环境变量3、修改配置文件4、上传驱动包5、拷贝jar包 二、import命令1、将mysql的数据导入到hdfs上2、将mysql的数据导入到hive上3、增量导入数据 三、export命令1、从hdfs导出到mysql中2、从hive导出到mysql…

【JPCS出版】第二届应用统计、建模与先进算法国际学术会议(ASMA2024,9月27日-29)

第二届应用统计、建模与先进算法国际学术会议 2024 2nd International Conference on Applied Statistics, Modeling and Advanced Algorithms(ASMA2024) 会议官方 会议官网:www.icasma.org 2024 2nd International Conference on Applied …

第四届计算机、信息工程与电子材料国际学术会议 (CTIEEM 2024)

目录 重要信息 大会简介 出版信息 大会组委 会议征稿主题 会议议程 参会须知 重要信息 大会时间:2024年11月15-17日 大会地点:中国-郑州 大会官网:www.ctieem.org 收录检索:EI Compendex,Scopus 大会简介 随着信…

XXL-JOB 漏洞大全

一、前言 在当今的数字化时代,任务调度平台对于企业级应用来说至关重要。它们负责自动化和协调各种时间敏感或周期性的任务,确保业务流程的顺畅运行。XXL-JOB作为一款流行的分布式任务调度平台,因其强大的功能和易用性,被广泛部署…

【4.3】图搜索算法-DFS和BFS解被围绕的区域

一、题目 给定一个二维的矩阵,包含 X 和 O ( 字母 O )。 找到所有被 X 围绕的区域,并将这些区域里所有的 O 用 X 填充。 示例 : X X X X X O O X X X O X X O X X 运行你的函数后,矩阵变为…