返回顶部
首页 > 资讯 > 数据库 >简单了解 MySQL 中相关的锁
  • 680
分享到

简单了解 MySQL 中相关的锁

2024-04-02 19:04:59 680人浏览 薄情痞子
摘要

本文主要是带大家快速了解 InnoDB 中锁相关的知识 基础概念解析和RocketMQ详细的源码解析 Http://xiazai.jb51.net/202105/yuanma/Roc

本文主要是带大家快速了解 InnoDB 中相关的知识

基础概念解析和RocketMQ详细的源码解析

Http://xiazai.jb51.net/202105/yuanma/RocketMQ_jb51.rar

为什么需要加锁

首先,为什么要加锁?我想我不用多说了,想象接下来的场景你就能 GET 了。

你在商场的卫生间上厕所,此时你一定会做的操作是啥?锁门。如果不锁门,上厕所上着上着,啪一下门就被打开了,可能大概也许似乎貌似有那么一丁点的不太合适。

数据也是一样,在并发的场景下,如果不对数据加锁,会直接破坏数据的一致性,并且如果你的业务涉及到钱,那后果就更严重了。

锁门表情包

锁的分类

在 InnoDB 中,都有哪些锁?其实你应该已经知道了很多了,例如面试中会问你存储引擎 MyISAM 和 InnoDB 的区别,你会说 MyIASM 只有表锁,但是 InnoDB 同时支持行锁和表锁。你可能还会被问到乐观锁和悲观锁的区别是啥。

锁的概念、名词很多,如果你没有对锁构建出一个完整的世界观,那么你理解起来就会比较有阻碍,接下来我们把这些锁给分一下类。

按照锁的粒度

按照锁的粒度进行划分可以分为:

  • 表锁
  • 行锁

这里就不讨论页锁了,页锁是 BDB(BerkeleyDB) 存储引擎中才有的概念,我们这里主要讨论 InnoDB 存储引擎。

按照锁的思想

按照加锁的思想可以分为:

  • 悲观锁
  • 乐观锁

这里的悲观、乐观和你平时理解的名词是同一个意思。乐观锁认为大概率不会发生冲突,只在必要的时候加锁。而悲观锁认为大概率会冲突,所以无论是否必要加锁都会执行加锁操作。

按照兼容性

按照兼容性可以把锁划分为:

  • 共享锁
  • 排他锁

被加上共享锁的资源,能够和其他人进行共享,而如果被加上了排他锁,其他人在拿不到这把锁的情况下是无法进行任何操作的。

按照锁的实现

这里的实现就是 InnoDB 中具体的锁的种类了,分别有:

  • 意向锁(Intention Locks)
  • 记录锁(Record Locks)
  • 间隙锁(Gap Locks)
  • 临键锁(Next-Key Locks)
  • 插入意向锁(Insert Intention Locks)
  • 自增锁(AUTO-INC Locks)

即使按照这种分类来对锁进行了划分,看到了这么多的锁的名词可能仍然会有点懵。比如我SELECT ... FOR UPDATE 的时候到底加的是什么锁?

我们应该透过现象看本质,本质是什么?本质是锁到底加在了什么对象上,而这个很好回答:

  • 加在了表上
  • 加在了行上

而对于加在行上的锁,其本质又是什么?本质是将锁加在了索引上。

意向锁

在 InnoDB 中支持了不同粒度的锁,行锁和表锁。例如lock tables命令就会持有对应表的排他锁。为了使多种不同粒度的锁更实用,InnoDB 设计了意向锁。

意向锁是一种表级锁,它表明了接下来的事务中,会使用哪种类型的锁,它有以下两种类型:

  • 共享意向锁(IS) 表明该事务会打算对表中的记录加共享锁
  • 独占意向锁(IX) 则是加排他锁

例如,select ... for share就是加的共享意向锁,而SELECT .. FOR UPDATE则是加的独占意向锁。其规则如下:

  • 一个事务如果想要获取某张表中某行的共享锁,它必须先获取该表的共享意向锁,或者独占意向锁。
  • 同理,如果想获取排他锁,它必须先获取独占意向锁

下图是这几种锁的组合下相互互斥、兼容的情况

对照上面的表,在相互兼容的情况下,对应的事务就能获取锁,但是如果不兼容则无法获取锁,直到不兼容的锁释放之后才能获取。

看到这里你可能就会有问题了,那既然意向锁除了 LOCK TBALES 之外什么都不阻塞。那我要它何用?

还是通过例子,假设事务 A 获取了 student 表中 id = 100 这行的共享锁,之后事务 B 需要申请 student 表的排他锁。而这两把锁明显是冲突的,而且还是对于同一行。

那 InnoDB 需要如何感知 A 获取了这把锁?遍历整个 B+ 树吗?不,答案就是意向锁。事务 B 申请写表的排他锁时,InnoDB 会发现事务 A 已经获取了该表的意向共享锁,说明 student 表中已经有记录被共享锁锁住了。此时就会阻塞住。

并且,意向锁除了像LOCK TABLES这种操作之外,不会阻塞其他任何操作。换句话说,意向锁只会和表级别的锁之间发生冲突,而不会和行级锁发生冲突。因为意向锁的主要目的是为了表明有人即将、或者正在锁定某一行。

就像你去图书馆找书,你并不需要每个书架挨着挨着找,直接去服务台用电脑一搜,就知道图书馆有没有这本书。

记录锁

这就是记录锁,是行锁的一种。记录锁的锁定对象是对应那行数据所对应的索引。对索引不太清楚的可以看看这篇文章。

当我们执行SELECT * FROM student WHERE id = 1 FOR UPDATE语句时,就会对值为1的索引加上记录锁。至于要是一张表里没有索引该怎么办?这个问题在上面提到的文章中也解释过了,当一张表没有定义主键时,InnoDB 会创建一个隐藏的RowID,并以此 RowID 来创建聚簇索引。后续的记录锁也会加到这个隐藏的聚簇索引上。

当我们开启一个事务去更新 id = 1 这行数据时,如果我们不马上提交事务,然后再启一个事务去更新 id = 1 的行,此时使用 show engine innodb status查看,我们可以看到lock_mode X locks rec but not gap waiting的字样。

X是排他锁的意思,从这可以看出来,记录锁其实也可以分为共享锁、排他锁模式。当我们使用FOR UPDATE是排他,而使用LOCK IN SHARE MODE 则是共享。

而在上面字样中出现的 gap 就是另一种行锁的实现间隙锁。

间隙锁

对于间隙锁(Gap Locks)而言,其锁定的对象也是索引。为了更好的了解间隙锁,我们举个例子。


SELECT name FROM student WHERE age BETWEEN 18 AND 25 FOR UPDATE

假设我们为 age 建立了非聚簇索引,运行该语句会阻止其他事务向 student 表中新增 18-25 的数据,无论表中是否真的有 age 为 18-25 的数据。因为间隙锁的本质是锁住了索引上的一个范围,而 InnoDB 中索引在底层的B+树上的存储是有序的。

再举个例子:


SELECT * FROM student WHERE age = 10 FOR UPDATE;

值得注意的是,这里的 age 不是唯一索引,就是一个简单的非聚簇索引。此时会给 age = 10 的数据加上记录锁,并且锁定 age < 10 的 Gap。如果当前这个事务不提交,其他事务如果要插入一条 age < 10 的数据时,会被阻塞住。

间隙锁是 Mysql 在对性能、并发综合考虑之下的一种折中的解决方案,并且只在**可重复读(RR)下可用,如果当前事务的隔离级别为读已提交(RC)**时,MySQL会将间隙锁禁用。

刚刚说了,记录锁分为共享、排他,间隙锁其实也一样。但是不同于记录锁的一点,共享间隙锁、排他间隙锁相互不互斥,这是怎么回事?

我们还是需要透过现象看到本质,间隙锁的目的是什么?

为了防止其他事务在 Gap 中插入数据

那共享、排他间隙锁在这个目标上是一致的,所以是可以同时存在的。

临键锁

临键锁(Next-Key Locks)是 InnoDB 最后一种行锁的实现,临键锁实际上是记录锁和间隙锁的组合。换句话说,临键锁会给对应的索引加上记录锁,并且外加锁定一个区间。

但是并不是所有临键锁都是这么玩的,对于下面的sql:


SELECT * FROM student WHERE id = 23;

在这种情况下,id是主键,唯一索引,无论其他事务插入了多少数据,id = 23这条数据永远也只有一条。此时再加一个间隙锁就完全没有必要了,反而会降低并发。所以,在使用的索引是唯一索引的时候,临键锁会降级为记录锁。

假设我们有10,20,30总共3条索引数据。那么对应临键锁来说,可能锁定的区间就会如下:

  • (∞, 10]
  • (10, 20]
  • (20, 30]
  • (30, ∞)

InnoDB 的默认事务隔离级别为可重复读(RR),在这个情况下,InnoDB 就会使用临键锁,以防止幻读的出现。

简单解释一下幻读,就是在事务内,你执行了两次查询,第一次查询出来 5 条数据,但是第二次再查,居然查出了 7 条数据,这就是幻读。

可能你在之前的很多博客,或者面试八股文上,了解到过 InnoDB 的RR事务隔离级别可以防止幻读,RR防止幻读的关键就是临键锁。

举个例子,假设 student 表中就两行数据,id分别为90和110.


SELECT * FROM student WHERE id > 100 FOR UPDATE;

当执行该 SQL 语句之后,InnoDB就会给区间 (90, 110] 和(110,∞) 加上间隙锁,同时给 id=110 的索引加上记录锁。这样以来,其他事务就无法向这个区间内新增数据,即使 100 根本不存在。

插入意向锁

接下来是插入意向锁(Insert Intention Locks),当我们执行 INSERT 语句之前会加的锁。本质上是间隙锁的一种。

还是举个例子,假设我们现在有索引记录10、20,事务A、B分别插入索引值为14、16的数据,此时事务A和B都会用插入意向锁锁住 10-20 之间的 Gap,获取了插入意向锁之后就会获取14、16的排他锁。

此时事务A和B是不会相互阻塞的,因为他们插入的是不同的行。

自增锁

最后是自增锁(AUTO-INC Locks),自增锁的本质是表锁,较为特殊。当事务 A 向包含了 AUTO_INCREMENT 列的表中新增数据时,就会持有自增锁。而此时其他的事务 B 则必须要等待,以保证事务 A 取得连续的自增值,中间不会有断层。

好了,通过下面链接获取MQ学习资料,包含基础概念解析和RocketMQ详细的源码解析,持续更新中,大家一定不要错过这份学习资料哦。

http://xiazai.jb51.net/202105/yuanma/RocketMQ_jb51.rar (必收藏)

以上就是简单了解 mysql 中相关的锁的详细内容,更多关于MySQL锁相关的资料请关注编程网其它相关文章!

您可能感兴趣的文档:

--结束END--

本文标题: 简单了解 MySQL 中相关的锁

本文链接: https://lsjlt.com/news/126741.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 简单了解 MySQL 中相关的锁
    本文主要是带大家快速了解 InnoDB 中锁相关的知识 基础概念解析和RocketMQ详细的源码解析 http://xiazai.jb51.net/202105/yuanma/Roc...
    99+
    2024-04-02
  • 简单了解mysql InnoDB MyISAM相关区别
    前言 mysql支持很多表类型的表(即存储引擎),如myisam、innodb、memory、archive、example等。每种存储引擎都有自己的优点和缺点,充分的理解每种存储引擎,有助于合理的使用它们。有人认为...
    99+
    2022-05-15
    mysql InnoDB MyISAM
  • MySQL中锁的相关问题
    锁分类: 从对数据操作的粒度分 : 表锁:操作时,会锁定整个表。行锁:操作时,会锁定当前操作行。 从对数据操作的类型分: 读锁(共享锁):针对同一份数据,多个读操作可以同时进行而不会...
    99+
    2024-04-02
  • MySQL InnoDB 锁的相关总结
    1.  Shared and Exclusive Locks shared lock (译:共享锁) exclusive lock (译:排它锁、独占锁) InnoDB实现了标准的行级锁,其中有两种类型的锁...
    99+
    2022-05-16
    MySQL InnoDB InnoDB锁
  • MySQL 锁的相关知识总结
    MySQL中的锁 锁是为了解决并发环境下资源竞争的手段,其中乐观并发控制,悲观并发控制和多版本并发控制是数据库并发控制主要采用的技术手段(具体可见我之前的文章),而MySQL中的锁就是其中的悲观并发控制。 MySQ...
    99+
    2022-05-14
    MySQL
  • MySQL中information_schema库中关于锁相关表的字段解释有哪些
    这篇文章主要为大家展示了“MySQL中information_schema库中关于锁相关表的字段解释有哪些”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“MySQ...
    99+
    2024-04-02
  • 怎样分析MySQL中锁的相关问题
    这篇文章给大家介绍怎样分析MySQL中锁的相关问题,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。锁分类:从对数据操作的粒度分 :表锁:操作时,会锁定整个表。行锁:操作时,会锁定当前操作行。从对数据操作的类型分:读锁(共...
    99+
    2023-06-22
  • MySQL实战 | 06/07 简单说说MySQL中的锁
    锁是计算机协调多个进程或纯线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所在有数据库必...
    99+
    2024-04-02
  • 简单了解mysql的日志管理
    本篇文章给大家主要讲的是关于mysql的日志管理的内容,感兴趣的话就一起来看看这篇文章吧,相信看完mysql的日志管理对大家多少有点参考价值吧。/etc/my.cnferror log   &nb...
    99+
    2024-04-02
  • Mysql在项目中相关使用(简单操作数据库)
    @作者 : SYFStrive @博客首页 : HomePage 📜: Mysq数据库 📌:个人社区(欢迎大佬们加入) 👉:社区链接...
    99+
    2023-09-07
    数据库 nosql mysql
  • MySQL 锁的一些简单概念
    1. 锁的粒度  在MySQL中,只要有多个请求需要在同一时刻修改数据,都会产生并发控制的问题。而锁的作用可以保证同一资源能被某个请求唯一使用。 加锁是会消耗系统资源的,包括获得锁、检查锁是否已解除、释放锁等等操作,都会增加系统的...
    99+
    2020-05-02
    MySQL 锁的一些简单概念
  • 简单了解MySQL存储引擎
    1. MySql体系结构 在介绍存储引擎之前先来介绍下MySql的体系结构,以便大家知道存储引擎在MySql整个体系中处于什么位置。下图是官方提供的一张架构图: MySQL体系结构图 从上图可以发现,MySQL由以...
    99+
    2022-05-15
    MySQL 存储引擎 MySQL 引擎
  • 简单了解mysql基础知识
    下面一起来了解下mysql基础知识,相信大家看完肯定会受益匪浅,文字在精不在多,希望mysql基础知识这篇短内容是你想要的。           ...
    99+
    2024-04-02
  • 简单了解JavaScript中的new Function
    目录前言1、语法01).无效的 JSON 对象字符串合法化02).模板字符串作为模板前言 JavaScript技术一直处于不断发展壮大中,如果你是前端开发人员或者JavaScript...
    99+
    2024-04-02
  • 简单了解Mysql中的索引,事务与视图
    下面一起来了解下Mysql中的索引,事务与视图,相信大家看完肯定会受益匪浅,文字在精不在多,希望Mysql中的索引,事务与视图这篇短内容是你想要的。索引的概念索引是一种特殊的文件,包含着对数据表中所有记录的...
    99+
    2024-04-02
  • 简单说说JVM堆区的相关知识
    一、堆概述 一个jvm实例(进程)只存在一个堆内存,堆也是java内存管理的核心区域。 java 堆区在jvm启动时即被创建,其空间大小也就被确定了 《ja...
    99+
    2024-04-02
  • 详解mysql中的concat相关函数
    一、concat()函数 功能:将多个字符串连接成一个字符串 语法:concat(str1,str2,…) 其中的字符串既可以是数据表字段,也可以是指定的字符串 返回结果为连接参数产生的...
    99+
    2024-04-02
  • MySQL关闭SSL的简单方法
    目录mysql关闭SSL方法远程连接MySQL8.0取消SSL验证总结MySQL关闭SSL方法 1、查看是否开启SSL: SHOW VARIABLES LIKE '%ssl%'; 看到have_ssl的值为YES,表示...
    99+
    2023-02-10
    MySQL关闭SSL MySQLSSL MySQL关闭SSL方法
  • 一文简单了解MySQL前缀索引
    当要索引的列字符很多时 索引则会很大且变慢 ( 可以只索引列开始的部分字符串 节约索引空间 从而提高索引效率 ) 原则: 降低重复的索引值 例如现在有一个地区表 areagdpcod...
    99+
    2024-04-02
  • 简单了解Python中的几种函数
    几个特殊的函数(待补充) python是支持多种范型的语言,可以进行所谓函数式编程,其突出体现在有这么几个函数: filter、map、reduce、lambda、yield lambda >&...
    99+
    2022-06-04
    几种 函数 简单
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作