mysql-死锁

文章目录

  • 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.rhkb.cn/news/428521.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

GRE隧道在实际部署中的优化、局限性与弊端

GRE的其他特性 上一篇光讲解配置就花了大量的篇幅,还一些特性没有讲解的,这里在来提及下。 1、动态路由协议 在上一篇中是使用的静态路由,那么在动态路由协议中应该怎么配置呢? undoip route-static 192.168.20.0 255.255.255.0 …

element-plus的菜单组件el-menu

菜单是几乎是每个管理系统的软件系统中不可或缺的,element-plus提供的菜单组件可以快速完成大部分的菜单的需求开发, 该组件内置和vue-router的集成,使用起来很方便。 主要组件如下 el-menu 顶级菜单组件 主要属性 mode:决定菜单的展示模式…

2024/9/20 使用QT实现扫雷游戏

有三种难度初级6x6 中级10x10 高级16x16 完成游戏 游戏失败后&#xff0c;无法再次完成游戏&#xff0c;只能重新开始一局 对Qpushbutton进行重写 mybutton.h #ifndef MYBUTTON_H #define MYBUTTON_H #include <QObject> #include <QWidget> #include <QPus…

2024年8月HarmonyOS鸿蒙应用开发者高级认证全新题库

有题库在手&#xff0c;一小时轻松拿下鸿蒙高级。你们需要也可以无偿分享哦&#xff01; 项目需要为不同的设备形态(如手机 、 智能手表)提供定制化构建 。请说明如何在 DevEcostudio 中 设置不同的构建配置&#xff0c; 以生成针对不同设备的 hap 包&#xff1a; 在模块级别 b…

JavaWeb的Filter详解

过滤器Filter 什么是Filter&#xff1f; 依据字面上的中文意思为过滤器。Filter的作用 当用户的请求到达指定的URL之前&#xff0c;可以借助Filter来改变这些请求的内容&#xff1b;同样地&#xff0c;当响应结果到达客户端之前&#xff0c;可以使用Filter修改输出的内容。什么…

【数据结构入门】排序算法之三路划分与非比较排序

文章目录 前言 一、三路划分优化 1.1. 基本思想 1.2. 实现步骤 1.3. 优点 1.4 代码实现 二、非比较排序 2.1 计数排序 2.1.1基本思想 2.1.2具体步骤 2.1.3算法特性 2.1.4算法实现 2.2 基数排序 2.2.1基本思想 2.2.2具体步骤 2.2.3 基数排序的方法 2.2.4算法特…

MongoDB在Linux系统中的安装与配置指南

在这篇文章中&#xff0c;我们将介绍如何在CentOS 7服务器上安装MongoDB&#xff0c;并通过DataX将数据从MongoDB迁移到MySQL数据库。这将包括MongoDB的安装、配置、数据准备以及使用DataX进行数据迁移的详细步骤。 MongoDB简介 MongoDB是一个高性能、开源、无模式的文档型数据…

Leetcode面试经典150题-97.交错字符串

给定三个字符串 s1、s2、s3&#xff0c;请你帮忙验证 s3 是否是由 s1 和 s2 交错 组成的。 两个字符串 s 和 t 交错 的定义与过程如下&#xff0c;其中每个字符串都会被分割成若干 非空 子字符串 &#xff1a; s s1 s2 ... snt t1 t2 ... tm|n - m| < 1交错 是…

Springboot3 + MyBatis-Plus + MySql + Uniapp 实现商品规格选择sku(附带自设计数据库,最新保姆级教程)

Springboot3 MyBatis-Plus MySql Uniapp 实现商品规格选择sku&#xff08;附带自设计数据库&#xff0c;最新保姆级教程&#xff09; 1、效果展示2、数据库设计2.1 商品表2.2 商品价格和规格中间表2.3 商品规格表 3、后端代码3.1 model3.2 vo3.3 mapper、server、serverImp3…

使用express或koa或nginx部署history路由模式的单页面应用

使用hash模式会有#&#xff0c;影响美观&#xff0c;所以使用history模式会是个更好的选择。 前端项目打包上线部署&#xff0c;可以使用下面的方式部署history模式的项目&#xff0c;下面以 jyH5 为例 expressjs部署 express脚手架搭建的app.js中添加如下代码&#xff1a; …

CDA Level 1 业务数据分析

目录 理解业务数据分析方法、掌握业务数据分析流程、能够使用及设计创建业务指标、能够结合业务模型及业务分析方法正确理解业务问题&#xff0c;找到问题原因&#xff0c;并能够提出解决问题建议&#xff0c;这个章节的应用会考的比较多&#xff08;终于正经起来了呢&#xf…

设计模式 组合模式(Composite Pattern)

组合模式简绍 组合模式&#xff08;Composite Pattern&#xff09;是一种结构型设计模式&#xff0c;它允许你将对象组合成树形结构来表示“部分-整体”的层次结构。组合模式使得客户端可以用一致的方式处理单个对象和组合对象。这样&#xff0c;可以在不知道对象具体类型的条…

7--SpringBoot-后端开发、原理详解(面试高频提问点)

目录 SpringBoot原理 起步依赖 自动配置 配置优先级 Bean设置 获取Bean 第三方Bean SpringBoot原理 内容偏向于底层的原理分析 基于Spring框架进行项目的开发有两个不足的地方&#xff1a; 在pom.xml中依赖配置比较繁琐&#xff0c;在项目开发时&#xff0c;需要自己去找…

手写Spring

简单实现Spring基于注解配置 ComponentScan Target(ElementType.TYPE) Retention(RetentionPolicy.RUNTIME) public interface ComponentScan {String value() default ""; } 相当于component-scan HspSpringConfig ComponentScan(value "spring.write.com…

C#自定义曲线绘图面板

一、实现功能 1、显示面板绘制。 2、拖动面板&#xff0c;X轴、Y轴都可以拖动。 3、显示面板缩放&#xff0c;放大或者缩小。 4、鼠标在面板中对应的XY轴数值。 5、自动生成的数据数组&#xff0c;曲线显示。 6、鼠标是否在曲线上检测。 二、界面 拖动面板 鼠标在曲线上…

【随手笔记】使用J-LINK读写芯片内存数据

第一种使用JLINK.exe 1. 打开j-link.exe 2.输入【usb】 3. 连接芯片 输入【connect】输入芯片型号【STM32L071RB】输入连接方式 【S】 使用SWD连接方式输入连接速率 【4000】连接成功 4. 输入【&#xff1f;】查看指令提示 5. 读写指令 Mem Mem [<Zone>…

DataFrame生成excel后为什么多了一行数字

问题描述 python查询数据生成excel文件&#xff0c;生成的excel多了第一行数字索引&#xff0c;1,2,3,4,5...... 代码&#xff1a; df pd.DataFrame(data)df.to_excel(filename, sheet_name用户信息表, indexFalse) 解决&#xff1a; 原理也很简单&#xff0c;就是设置个参…

【python设计模式7】行为型模式2

目录 策略模式 模板方法模式 策略模式 定义一个个算法&#xff0c;把它们封装起来&#xff0c;并且使它们可以相互替换。本模式使得算法可独立于使用它的客户而变化。角色有&#xff1a;抽象策略、具体策略和上下文。 from abc import abstractmethod, ABCMeta from datetim…

前端vue-ref与document.querySelector的对比

ref只在本组件中查找&#xff0c;而document.querySelector是在整个页面查找

Golang | Leetcode Golang题解之第414题第三大的数

题目&#xff1a; 题解&#xff1a; func thirdMax(nums []int) int {var a, b, c *intfor _, num : range nums {num : numif a nil || num > *a {a, b, c &num, a, b} else if *a > num && (b nil || num > *b) {b, c &num, b} else if b ! ni…