MySQL 锁分类有哪些?一文带你详解!!

MySQL 锁

    • 全局锁
      • 全局锁的应用场景
      • 全局锁的缺点
    • 表级锁
      • 表锁
      • 元数据(MDL)锁
        • MDL 锁的问题
      • 意向锁
      • AUTO-INC 锁
    • 行级锁
      • 记录锁(Record Lock)
      • 间隙锁(Gap Lock)
      • 临键锁(Next-Key Lock)
      • 插入意向锁

首先让我们创建一张用户表,并插入一些数据:

CREATE TABLE userinfo (user_id INT PRIMARY KEY AUTO_INCREMENT,username VARCHAR(50) NOT NULL,password VARCHAR(50) NOT NULL,email VARCHAR(100),created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);INSERT INTO userinfo (username, password, email) VALUES ('张三', 'password123', 'zhangsan@example.com');
INSERT INTO userinfo (username, password, email) VALUES ('李四', 'password456', 'lisi@example.com');
INSERT INTO userinfo (username, password, email) VALUES ('王五', 'password789', 'wangwu@example.com');

全局锁

插入全局锁的命令

flush tables with read lock

执行后,整个数据库就处于只读状态了,这时其他线程执行以下操作,都会被阻塞:

  • 对数据的增删改操作,比如 insert、delete、update等语句;
  • 对表结构的更改操作,比如 alter table、drop table 等语句。

比如此时我们想插入一条语句,但显示被读锁阻塞住了
在这里插入图片描述
执行释放锁之后的命令就可以插入成功了

unlock tables;

在这里插入图片描述

全局锁的应用场景

全局锁的应用场景主要应用于 全库逻辑备份

举个例子,如果不加读写锁的话

在备份用户表和商品表的时候,有一个用户购买了一件商品

就会导致备份的数据 是扣减前的用户余额 和 扣减后的商品余额 —— 用户余额没变,货却没了!

在这里插入图片描述

全局锁的缺点

加上全局锁后,数据库就变成了 只读状态

那么如果数据库有很多数据,备份就会花费很多时间,而且备份期间只能读数据而不能更新数据,就会导致业务的停滞

那有什么办法可以改进呢?

可以利用 MVCC 机制,在可重复读隔离级别下,开启事务后,会先创建一个 Read View,然后整个事务执行期间都会使用这个 Read View,同时也依然可以对数据进行更新操作。

这就是事务四大特性的 隔离性,这样备份期间备份的数据一直都是在开启事务时的数据。

注意,这需要能够适用 可重复读隔离级别 下的存储引擎,比如 Innodb。

但是 MyISAM 这种不支持事务的引擎,在备份数据库时就要使用全局锁的方法了。

表级锁

表锁

表锁有两种:

//表级别的共享锁,也就是读锁;
lock tables t_student read;//表级别的独占锁,也就是写锁;
lock tables t_stuent write;

这里的锁有点乱,我们可以做四次实验试试看

  1. 给表设置读锁,然后读数据,发现是正常没问题的
    在这里插入图片描述
  2. 然后我们进行写数据,发现被阻塞住了
    在这里插入图片描述

如图,这里我们给用户表设置了读锁,然后想写入一条数据,发现被阻塞住了

在这里插入图片描述

说明这里的本线程的表级别的读锁,会限制住本线程的写操作

  1. 我们解开表级锁,并设置读锁,然后再进行读操作

在这里插入图片描述
发现这里,阻塞住了,陷入了死锁状态,注意右下角的查询时间,这里是一直在查询没停止的(我只是截了个图),说明本线程的写锁也会限制住本线程的读操作

  1. 我们在写锁下进行写操作,正常没问题
    在这里插入图片描述

所以,可以看出来,表锁除了会限制别的线程的读写外,也会限制本线程接下来的读写操作。

所以,表锁的颗粒度是很大的,会影响到并发性能,尽量要避免使用,Innodb 牛逼的地方在于实现了颗粒度更细的行级锁。

元数据(MDL)锁

我们不需要显示的使用 MDL,因为当我们对数据库表进行操作时,会自动给这个表加上 MDL:

  • 当我们对一张表进行 CRUD 操作时,会对表加一个 元数据读锁;
  • 当我们对一张表的结构进行操作的时候,会对表加一个 元数据写锁

MDL 是为了保证当用户对表执行 CRUD 操作时,防止其他线程对这个表结构做了变更。

当有线程在执行 select 语句( 加 MDL 读锁)的期间,如果有其他线程要更改该表的结构( 申请 MDL 写锁),那么将会被阻塞,直到执行完 select 语句( 释放 MDL 读锁)。

反之,当有线程对表结构进行变更( 加 MDL 写锁)的期间,如果有其他线程执行了 CRUD 操作( 申请 MDL 读锁),那么就会被阻塞,直到表结构变更完成( 释放 MDL 写锁)。

MDL 锁的问题

MDL 是在事务提交之后才会释放的,也就是说,事务执行期间,MDL 是一直持有的

那如果数据库中有一个长事务,也就是开启之后一直没提交的事务,那当我们对表结构做变更操作的时候,可能就会出现一些问题:

  1. 线程A 开启了事务
  2. 线程A 执行了一条查询 select 语句,这时会加 MDL读锁
  3. 线程B 执行了一条查询 select 语句,这时不会阻塞,因为读读并不冲突
  4. 线程C 试图修改表字段,但此时事务A 并没有提交,所以 MDL 读锁就还占用着,此时线程C 就无法申请到 MDL 写锁,而导致阻塞
  5. 之后的线程 D、E、F 想要执行查询语句时,就会被阻塞住,然后数据库的线程就会爆满
    在这里插入图片描述

为什么写锁阻塞住,读锁也会被阻塞住?

因为 申请 MDL 锁的操作会形成一个队列,队列中 写锁获取的优先级高于读锁,一旦出现MDL 写锁等待,就会阻塞住该表的所有 CRUD 操作

在这里插入图片描述
所以,为了能安全的对表结构进行变更,在变更之前,我们要先看看数据库中的长事务,是否有事务已经对表加上了 MDL读锁,如果可以就考虑先 kill 掉他,然后再做变更。

意向锁

意向锁有两种:意向共享锁、意向排他锁:

  • 意向共享锁(Intention Shared Lock,IS):当一个事务请求获取一个行级锁或表级锁时,InnoDB会自动获取相应的表的意向锁。

这个锁表明事务打算以共享方式(读取)访问数据。其他事务在查询数据时,可以通过检查意向锁来快速确定是否有任何行级锁冲突,而无需检查表中每一行的锁状态。

  • 意向排他锁(Intention Exclusive Lock,IX):与意向共享锁类似,意向排他锁表明事务打算以排他方式(写入)访问数据。

当事务持有意向排他锁时,其他事务不能获取意向共享锁,从而防止其他读取操作的干扰。

也就是说,当执行插入、更新、删除操作,需要先对表加上「意向独占锁」,然后对该记录加独占锁。

而普通的 select 是不会加行级锁的,普通的 select 语句是利用 MVCC 实现一致性读,是无锁的。

不过,select 也是可以对记录加共享锁和独占锁的,具体方式如下:

//先在表上加上意向共享锁,然后对读取的记录加共享锁 
select ... lock in share mode;  //先表上加上意向独占锁,然后对读取的记录加独占锁 
select ... for update;

意向共享锁和意向独占锁是表级锁,不会和行级的共享锁和独占锁发生冲突,而且意向锁之间也不会发生冲突,只会和共享表锁(lock tables … read)和独占表锁(lock tables … write)发生冲突。

表锁和行锁是满足读读共享、读写互斥、写写互斥的。

如果没有「意向锁」,那么加「独占表锁」时,就需要遍历表里所有记录,查看是否有记录存在独占锁,这样效率会很慢。

那么有了「意向锁」,由于在对记录加独占锁前,先会加上表级别的意向独占锁,那么在加「独占表锁」时,直接查该表是否有意向独占锁,如果有就意味着表里已经有记录被加了独占锁,这样就不用去遍历表里的记录。

所以,意向锁的目的是为了快速判断表里是否有记录被加锁。

AUTO-INC 锁

auto-inc 锁(AUTO-INCREMENT lock),是InnoDB中用于处理自动增长(AUTO_INCREMENT)字段的一种特殊的锁定机制。当向表中插入数据时,如果该表包含有AUTO_INCREMENT列,并且你需要为这个列指定一个值,那么会涉及到auto-inc锁。

auto-inc锁的主要目的是确保在同一事务中插入的记录能够获得连续的AUTO_INCREMENT值。在并发插入的场景中,这可以避免插入操作之间的干扰,确保插入的顺序性。

行级锁

InnoDB 是支持行级锁的,而 MyISAM 是不支持的

记录锁(Record Lock)

记录锁是行级锁的一种,它针对数据表中的单个记录进行锁定,有 S 锁 和 X 锁之分,也就是共享锁和独占锁之分。

一个事务对一条记录加了 S 锁,其他事务可以加 S 锁,但不能加 X 锁

一个事务对一条记录加了 X 锁,其他事务 S 锁和 X 锁都不能加

记录锁通常是通过索引项来实现的,即数据库会锁定索引项来实现对行的锁定。

在这里插入图片描述

间隙锁(Gap Lock)

Gap Lock是锁定数据表中两个记录之间的空隙(即间隙锁)。

间隙锁只存在于可重复读隔离级别,目的是为了解决可重复读隔离级别下幻读的问题。

它用于防止其他事务插入新的记录,从而保护一个范围行的完整性。

Gap Lock不会锁定实际的行记录,而是锁定一个范围,阻止其他事务在这个范围内插入新行。

而且,间隙锁之间是不冲突的,可以相互兼容,只不过无法往间隙范围内插入数据

在这里插入图片描述

临键锁(Next-Key Lock)

Next-Key Lock是 记录锁 和 间隙锁 的组合。

它技能保护锁住的该条记录,又能阻止其他事务将其新纪录插入到被保护记录前面的间隙中

在这里插入图片描述

因为临键锁是包含 记录锁 + 间隙锁的,而间隙锁之间是可以相互兼容的,但记录锁就需要注意考虑 S 型 和 X 型的关系了

插入意向锁

插入意向锁是与上面的间隙锁对应生效的

如果一条记录的位置已经被其他事务加了间隙锁(当然,也包含临键锁中的间隙锁),那么,这个插入操作就会被阻塞,在此期间会生成一个 插入意向锁,表明有事务想要在某个区间插入新纪录,但是现在处于等待状态

比如事务 A 在一个区间内加了间隙锁,然后事务 B 想要在该区间插入一条语句,这时候发现有个间隙锁,于是就会生成一个 插入意向锁,然后将锁呢设置为等待状态。

MySQL 加锁的时候,会先生成锁结构,然后设置锁状态,锁状态为正常状态,就表示事务获取到了锁,如果为等待状态,就意味着没有获取到锁

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

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

相关文章

Opencv中的直方图(2)计算图像的直方图函数calcHist()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 计算一组数组的直方图。 函数 cv::calcHist 计算一个或多个数组的直方图。用于递增直方图bin的元组的元素是从相同位置的相应输入数组中获取的。…

vue多环境配置和打包

件名的后缀来指定它们仅在特定模式下被加载。 .env:所有环境下都会加载的通用配置。 .env.local:本地覆盖配置,不加入版本控制。 .env.[mode]:仅为指定的模式加载的配置文件,例如.env.development、.env.production、…

Cursor是什么?Cursor Pro Plus 如何订阅升级教程

一、Cursor是什么? Cursor 是一个基于 Visual Studio Code(VS Code)技术构建的高级代码编辑器,专为提高编程效率并更深度地整合 AI 功能而设计。它不仅继承了 VS Code 的强大功能和用户界面,还增加了专门针对 AI 支持…

Agent(智能体)和 MetaGPT,一句话实现整个需求应用代码

前面 2 篇文章,我们使用文生文、文生图和文生音频三个大模型共同实现了图文并茂的儿童绘本故事和绘本故事音频需求: 第一篇 根据主题生成儿童绘本故事:GLM-4-Flash 大模型 API 免费了,手把手构建“儿童绘本”应用实战&#xff08…

Nuxt3入门:过渡效果(第5节)

你好同学&#xff0c;我是沐爸&#xff0c;欢迎点赞、收藏、评论和关注。 Nuxt 利用 Vue 的 <Transition> 组件在页面和布局之间应用过渡效果。 一、页面过渡效果 你可以启用页面过渡效果&#xff0c;以便对所有页面应用自动过渡效果。 nuxt.config.js export defaul…

概率DP (由一道绿题引起的若干问题。目前为一些老题,蒟蒻的尝试学习1.0)

概率DP&#xff1a; 利用动态规划去解决 概率 期望 的题目。 概率DP 求概率&#xff08;采用顺推&#xff09; 从 初始状态推向结果&#xff0c;同一般的DP类似&#xff0c;只是经历了概率论知识的包装。 老题&#xff1a; 添加链接描述 题意&#xff1a; 袋子里有w只白鼠&am…

linux编译器——gcc/g++

1.gcc linux上先要安装&#xff0c; sudo yum install gcc gcc --version 可以查看当前的版本 &#xff0c;我们默认安装的是4.8.5的版本&#xff0c;比较低&#xff0c; gcc test.c -stdc99 可以使他支持更高版本的c标准 -o 可以殖指明生成文件的名字&#xff0c;可以自己…

上海市计算机学会竞赛平台2024年7月月赛丙组求和问题

题目描述 给定 nn 个整数 a1,a2,…,ana1​,a2​,…,an​&#xff0c;请问这个序列最长有多少长的前缀&#xff0c;满足元素的和大于或等于 00&#xff1f;如果任何长度大于 00 的前缀之和都为负数&#xff0c;则输出 00 输入格式 第一行&#xff1a;单个整数表示 nn第二行&a…

经验笔记:JSP(JavaServer Pages)

JSP&#xff08;JavaServer Pages&#xff09;经验笔记 JSP&#xff08;JavaServer Pages&#xff09;是一种用于创建动态网页的技术&#xff0c;它允许在HTML页面中嵌入Java代码&#xff0c;从而实现动态内容的生成。JSP与Servlet一样&#xff0c;都是Java EE平台的一部分&am…

随机森林的知识博客:原理与应用

随机森林&#xff08;Random Forest&#xff09;是一种基于决策树的集成学习算法&#xff0c;它通过组合多棵决策树的预测结果来提升模型的准确性和稳健性。随机森林具有强大的分类和回归能力&#xff0c;广泛应用于各种机器学习任务。本文将详细介绍随机森林的原理、构建方法及…

大数据系列之:Java8和java11查看进程堆内存使用情况

大数据系列之:Java8和java11查看进程堆内存使用情况 Java8查看进程堆内存java11查看进程堆内存进程堆内存使用情况评估Java8查看进程堆内存 jmap -F -heap 2723jmap -F -heap 2723是一个Java命令行工具jmap的使用示例。它用于生成Java进程2723的堆内存信息。其中,-F选项表示…

JavaSE-易错题集-001

1. AccessViolationException异常触发后&#xff0c;下列程序的输出结果为&#xff08; &#xff09; 1 2 3 4 5 6 7 8 9 10 11 12 13 static void Main(string[] args) { try { throw new AccessViolationException(); Console.Write…

OpenCV图像分割教程

OpenCV 图像分割教程 OpenCV 是一个非常强大的计算机视觉库&#xff0c;支持各种图像处理任务。图像分割是 OpenCV 支持的一个重要功能&#xff0c;它用于将图像划分为不同的区域&#xff0c;识别感兴趣的部分。我们将通过介绍 OpenCV 中的图像分割方法&#xff0c;包括基础功…

ubantu安装mysql + redis数据库并使用C/C++操作数据库

mysql 安装mysql ubuntu 安装 MySql_ubuntu安装mysql-CSDN博客 Ubuntu 安装 MySQL 密码设置_ubuntu安装mysql后设置密码-CSDN博客 service mysql restart1 C/C连接数据库 C/C 连接访问 MySQL数据库_c mysql-CSDN博客 ubuntu安装mysql的c开发环境_ubuntu 搭建mysql c开发…

测试一些概念

软件测试 软件测试流程 需求分析&#xff1a;在这个阶段&#xff0c;测试人员会审查和分析项目的需求文档&#xff0c;以确保他们理解需要测试的功能和特性。 制定测试计划&#xff1a;在这个阶段&#xff0c;测试人员会制定一个详细的测试计划&#xff0c;包括测试目标、测…

跨越技术壁垒:EasyCVR为何选择支持FMP4格式,重塑视频汇聚平台标准

随着物联网、大数据、云计算等技术的飞速发展&#xff0c;视频监控系统已经从传统的安防监控扩展到智慧城市、智能交通、工业制造等多个领域。视频流格式作为视频数据传输与存储的基础&#xff0c;其兼容性与效率直接影响到整个视频监控系统的性能。 在众多视频流格式中&#…

TCP Analysis Flags 之 TCP Port numbers reused

前言 默认情况下&#xff0c;Wireshark 的 TCP 解析器会跟踪每个 TCP 会话的状态&#xff0c;并在检测到问题或潜在问题时提供额外的信息。在第一次打开捕获文件时&#xff0c;会对每个 TCP 数据包进行一次分析&#xff0c;数据包按照它们在数据包列表中出现的顺序进行处理。可…

pytorch计算网络参数量和Flops

from torchsummary import summary summary(net, input_size(3, 256, 256), batch_size-1)输出的参数是除以一百万&#xff08;/1000000&#xff09;M&#xff0c; from fvcore.nn import FlopCountAnalysis inputs torch.randn(1, 3, 256, 256).cuda() flop_counter FlopCo…

停车场小程序如何实现分账功能?

智慧停车平台为什么迫切需要分账功能的原因&#xff0c;通过清结算系统提供的服务商分账功能&#xff0c;可以有效提高交易环节的分账效率。平台方只需要在后台配置好与各服务商、业主等多方分账规则&#xff0c;待交易订单形成后&#xff0c;清结算系统会自动化分账&#xff0…

十大口碑最好开放式蓝牙耳机是哪些?五款热销好用产品测评!

​开放式耳机现在超火&#xff0c;成了时尚、好看又舒服的代名词&#xff0c;迅速俘获了一大波粉丝&#xff0c;成了耳机界的新宠儿。跟那些传统的入耳式耳机比起来&#xff0c;开放式耳机戴着更稳&#xff0c;对耳朵也更友好。不过&#xff0c;也有人觉得这玩意儿不值&#xf…