0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

一文彻底搞懂MySQL锁究竟锁的啥2

jf_78858299 来源:蝉沐风的码场 作者:蝉沐风 2023-03-03 10:13 次阅读

6. 意向锁

6.1. 背景

前面提到的S锁和X锁的语法规则其实是针对记录的,也就是行锁,原因是InnoDB中行锁用的最多。如果将锁的粒度和锁的基本模式排列组合一下,就会出现如下4种情况:

  • 行级S
  • 行级X
  • 表级S
  • 表级X

那么接下来的描述,也就顺理成章了。

如果事务给一个表添加了表级S锁,则:

  • 其他事务可以继续获得该表的S锁,但是无法获取该表的X锁;
  • 其他事务可以继续获得该表某些行的S锁,但是无法获取该表某些行的X锁。

如果事务给一个表添加了表级X锁,则:

  • 不论是该表的S锁、X锁,还是该表某些行的S锁、X锁,其他事务都只能干瞪眼儿,啥也获取不了。

挺好理解的吧,总之就是 S锁只能和S锁相容,X锁和其他任何锁都互斥 。问题来了,虽然用的不多,但是万一我真的想给整个表添加一个S锁或者X锁怎么办?

假如我要给表user添加一个S锁,那就必须保证user在表级别上和行级别上都不能有X锁,表级别上还好说一点,无非就是1个内存结构罢了,但是行X锁呢?必须得逐行遍历是否有行X锁吗?

同理,假如我要给表user添加一个X锁,那就必须保证user在表级别上和行级别上都不能有任何锁(SX都不能有),难不成得逐行遍历是否有SX锁吗?

遍历是不可能遍历的!这辈子都不可能遍历的!于是, 意向锁 (Intension Lock)诞生了。

6.2. 概念

我们要避免遍历,那最好的办法就是在给行加锁时,先在表级别上添加一个标识。

  • 意向共享锁(Intension Shared Lock):简称IS锁,当事务试图给行添加S锁时,需要先在表级别上添加一个IS锁;
  • 意向排他锁(Intension Exclusive Lock):简称IX锁,当事务试图给行添加X锁时,需要先在表级别上添加一个IX锁。

这样一来:

  • 如果想给user表添加一个S锁(表级锁),就先看一下user表有没有IX锁;如果有,就说明user表的某些行被加了X锁(行锁),需要等到行的X锁释放,随即IX锁被释放,才可以在user表中添加S锁;
  • 如果想给user表添加一个X锁(表级锁),就先看一下user有没有IS锁或IX锁;如果有,就说明user表的某些行被加了S锁或X锁(行锁),需要等到所有行锁被释放,随即IS锁或IX锁被释放,才可以在user表中添加X锁。

需要注意的是,意向锁和意向锁之间是不冲突的,意向锁和行锁之间也不冲突。

只有在对表添加S锁或X锁时才需要判断当前表是否被添加了IS锁或IX锁,当为表添加IS锁或IX锁时,不需要关心当前表是否已经被添加了其他IS锁或IX锁。

目前为止MySQL锁的基本模式就介绍完了,接下来回到这片文章的题目,MySQL锁,锁住的到底是什么?由于InnoDB的行锁用的最多,这里的锁自然指的是行锁。

7. 行锁的原理

既然都叫行锁了,我们姑且猜测一下,行锁锁住的是一行数据。我们做个实验。

7.1. 没有任何索引的表

我们先创建一张没有任何索引的普通表,语句如下

CREATE TABLE `user_t1` (
  `id` int DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

表中数据如下:

mysql> SELECT * FROM user_t1;
+------+-------------+
| id   | name        |
+------+-------------+
|    1 | chanmufeng  |
|    2 | wanggangdan |
|    3 | wangshangju |
|    4 | zhaotiechui |
+------+-------------+

接下来我们在两个session中开启两个事务。

  • 事务1,我们通过WHERE id = 1“锁住”第1行数据;
  • 事务2,我们通过WHERE id = 2"锁住"第2行数据。

图片

一件诡异的事情是,第2个加锁的操作被阻塞了。实际上,T2中不管我们要给user_t1中哪行数据加锁,都会失败!

为什么我SELECT一条数据,却给我锁住了整个表?这个实验直接推翻了我们的猜测, InnoDB的行锁并非直接锁定Record行

为什么没有索引的情况下,给某条语句加锁会锁住整个表呢?别急,我们继续。

7.2. 有主键索引的表

我们再创建一个表user_t2,语句如下:

CREATE TABLE `user_t2` (
	`id` int NOT NULL,
	`name` varchar(255) DEFAULT NULL,
	PRIMARY KEY (`id`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

user_t1的不同之处在于为id创建了一个主键索引。表中数据依然如下:

mysql> SELECT * FROM user_t2;
+------+-------------+
| id   | name        |
+------+-------------+
|    1 | chanmufeng  |
|    2 | wanggangdan |
|    3 | wangshangju |
|    4 | zhaotiechui |
+------+-------------+

同样开启两个事务:

  • 事务1,通过WHERE id = 1“锁住”第1行数据;
  • 事务2
    • 依然使用WHERE id = 1尝试加锁,加锁失败;
    • 使用WHERE id = 2尝试加锁,加锁成功。

图片

既然锁的不是Record行,难不成锁的是id这一列吗?

我们再做最后一个实验。

7.3. 有唯一索引的表

我们再创建一个表user_t3,语句如下:

CREATE TABLE `user_t3` (
	`id` int NOT NULL,
	`name` varchar(255) DEFAULT NULL,
	PRIMARY KEY (`id`),
  UNIQUE KEY (`uk_name`) (`name`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4;

user_t2的不同之处在于为name列创建了一个唯一索引。表中数据依然如下:

mysql> SELECT * FROM user_t3;
+------+-------------+
| id   | name        |
+------+-------------+
|    1 | chanmufeng  |
|    2 | wanggangdan |
|    3 | wangshangju |
|    4 | zhaotiechui |
+------+-------------+

图片

两个事务:

  • 事务1,通过name字段 “锁住”name为“chanmufeng”的数据;
  • 事务2
    • 依然使用WHERE name = “chanmufeng” 尝试加锁,可以预料,加锁失败;
    • 使用WHERE id = 1尝试给同样的行加锁,加锁失败。

通过3个实验我们发现,行锁锁住的既不是Record行,也不是Column列,那到底锁住的是什么?我们对比一下,上文的3张表的不同点在于索引不同,其实 InnoDB的行锁,就是通过锁住索引来实现的

接下来回答3个问题。

8. 三个问题

8.1. 锁住索引?没有索引怎么办?

你说锁住索引?如果我不创建索引,MySQL锁定个啥?

如果我们没有设置主键,InnoDB会优先选取一个不包含NULL值的Unique键作为主键,如果表中连Unique键也没有的话,就会自动为每一条记录添加一个叫做DB_ROW_ID的列作为默认主键,只不过这个主键我们看不到罢了。

下图是数据的行格式。看不懂的话强烈推荐看一下我上面给出的两篇文章,说得非常明白。

图片

行格式

8.2. 为什么第一个实验会锁表?

因为SELECT没有用到索引,会进行全表扫描,然后把DB_ROW_ID作为默认主键的聚簇索引都给锁住了。

8.3. 为什么通过唯一索引给数据加锁,主键索引也会被锁住?

不管是Unique索引还是普通索引,它们的叶子结点中存储的数据都不完整,其中只是存储了作为索引并且排序好的列数据以及对应的主键值。

因此我们通过索引查找数据数据实际上是在索引的B+树中先找到对应的主键,然后根据主键再去主键索引的B+树的叶子结点中找到完整数据,最后返回。所以虽然是两个索引树,但实际上是同一行数据,必须全部锁住。

下面给了一张图,让不了解索引的朋友大致了解一下。上半部分是name列创建的唯一索引的B+树,下半部分是主键索引(也叫聚簇索引)。

假如我们通过WHERE name = '王钢蛋'对数据进行查询,会先用到name列的唯一索引,最终定位到主键值为1,然后再到主键索引中查询id = 1的数据,最终拿到完整的行数据。

这两张图在我索引文章中都有哦~

图片

MySQL锁-索引

9. 总结

至此,我已经回答了文章开头的绝大多数问题。

MySQL锁,是解决资源竞争问题的一种手段。有哪些竞争呢?读—写/写—读,写—写中都会出现资源竞争问题,不同的是前者可以通过MVCC的方式来解决,但是某些情况下你也不得不用锁,因此我也顺便解释了锁和MVCC的关系。

然后介绍了MySQL锁的基本模式,包括共享锁(S锁)和排他锁(X锁),还引入了意向锁。

最后解释了锁到底锁的是什么的问题。通过3个实验,最终解释了InnoDB锁本质上锁的是索引。

声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • 计算机
    +关注

    关注

    19

    文章

    6840

    浏览量

    85699
  • MySQL
    +关注

    关注

    1

    文章

    776

    浏览量

    26094
  • MVCC
    +关注

    关注

    0

    文章

    13

    浏览量

    1446
收藏 人收藏

    评论

    相关推荐

    什么是自?#自

    学习电子知识
    发布于 :2023年06月26日 19:35:52

    密码电路

    密码电路 使用中小型集成运放电路设计电阻密码要求完成以下功能Ø用个特定阻值的电阻作为密钥;Ø用Ucc/2作为比较电压;Ø用发光二极管的亮暗来显示
    发表于 08-31 13:01

    电子密码LCD12864中显示proteus仿真(含程序)

    电子密码LCD12864中显示,非常不错,毕业设计的同学的福音啊
    发表于 03-01 11:23

    电子密码

    (1)用电子器件设计制作个密码,使之在输入正确的代码时开锁。(2)在的控制电路中设个可以修改的4位代码,当输入的代码和控制电路的代码
    发表于 12-02 16:38

    转第16章 FreeRTOS调度,任务和中断

    16.7总结16.1调度调度就是RTOS提供的调度器开关函数,如果某个任务调用了调度开关函数,处于调度开和调度关之间的代码在执行期
    发表于 09-01 07:45

    请问DSPflash死后,RAM还可以用吗,还是这块芯片就彻底废了?

    本帖最后由 只耳朵怪 于 2018-6-13 16:47 编辑 请问DSPflash死后,RAM还可以用吗,还是这块芯片就彻底废了?
    发表于 06-13 04:19

    InnoDB的特点和状态查询

    MySQL探秘(五)InnoDB的类型和状态查询
    发表于 08-07 11:45

    带自功能的密码怎么设计?

    带自功能的密码设计原理
    发表于 03-25 08:35

    一锁互联”物联网新解决方案--一锁(三)

    ,成本最低,性价比最高!共分以下五个场所与主题:1.一锁仓储管理锁具在仓门处,通过授权开启进出货来监控。可用产品:智能挂锁、智能门锁2.一锁
    发表于 05-09 11:38

    基于MM32W系列开发的蓝牙智能方案

    智能方案中使用到灵动微MM32W系列低功耗MCU,配合手机通过APP读取智能蓝牙信息,尝试配对,配对成功即可正常通讯,手机APP通过蓝牙把指令发送给智能进行解锁,整个流程简单可靠,该方案将
    发表于 12-28 07:15

    读懂eMMC究竟

    eMMC究竟?eMMC长什么样?eMMC用在哪?主要是干嘛用的?eMMC究竟是如何工作的呢?
    发表于 06-18 06:04

    搞懂UPS主要内容

    导读:UPS是系统集成项目中常用到的设备,也是机房必备的设备。本文简单介绍了UPS的种类、功能、原理,品质选择与配置选择方式,基础维护等相关的内容。搞懂UPS本文主要内容:UPS种类、功能
    发表于 09-15 07:49

    开发板上电存的相关资料推荐

    时断电;但是我们可以给供电电路增加置电路,按下按键时通过设置特定的引脚,当按键弹起时置电路也可以让电源为开发板供电。这样可以实现休眠模式、低功耗模式等。2、供电置原理图3、供电置
    发表于 01-06 06:46

    请问下STM32为什么用SWD口烧录程序会导致死呢

    请问下STM32为什么用SWD口烧录程序会导致死呢?究竟是什么原因造成的呢?
    发表于 02-24 07:13

    一文彻底搞懂MySQL究竟锁的啥1

    MySQL锁系列文章已经鸽了挺久了,最近赶紧挤了挤时间,和大家聊一聊MySQL的锁。 只要学计算机,「`锁`」永远是一个绕不过的话题。MySQL锁也是一样。 一句话解释MySQL
    的头像 发表于 03-03 10:12 350次阅读
    一文<b class='flag-5'>彻底</b><b class='flag-5'>搞懂</b><b class='flag-5'>MySQL</b>锁<b class='flag-5'>究竟</b>锁的啥1