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

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

3天内不再提示

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

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

MySQL锁系列文章已经鸽了挺久了,最近赶紧挤了挤时间,和大家聊一聊MySQL的锁。

只要学计算机,「」永远是一个绕不过的话题。MySQL锁也是一样。

一句话解释MySQL锁:

MySQL锁是解决资源竞争的一种方案。

短短一句话却包含了3点值得我们注意的事情:

  1. 对什么资源进行竞争?
  2. 竞争的方式(或者说情形)有哪些?
  3. 锁是如何解决竞争的?

这篇文章开始带你循序渐进地理解这几个问题。

1. 资源的竞争方式

MySQL对资源的操作无非就是 两种方式,但是由于事务并发执行的存在,因此对同一资源的并发访问存在3种形式:

  • 读—读:并发事务同时读取相同资源。由于读操作不会改变资源本身,因此 这种情况下并不存在并发安全性问题
  • 读—写/写—读:一个事务对资源进行读操作,另一个事务对资源进行写操作。
  • 写—写:并发事务同时对同一个资源进行写操作。

2. 读—写/写—读下的问题

假设一种情形,一个事务先对某个资源进行读操作,然后另一个事务再对该资源进行写操作,如果两个事务到此为止,必然不会导致并发问题。

可是事务这种东西,一般情况下就是包含有很多个子操作啊。

2.1. 幻读

想象一下啊,假设事务T1T2并发执行,T1先查找了所有name为「王刚蛋」的用户信息,此时发现拥有这个硬汉名字的用户只有一个。然后T2插入了一个同样叫做「王刚蛋」的用户的信息,并且提交了。

图片

幻读

图片

2.2. 不可重复读

再来,同样是T1T2两个事务,T1通过id = 1查询到了一条数据,然后T2紧接着UPDATEDELETE也可以)了该条记录,不同的是,T2紧接着通过COMMIT提交了事务。

图片

此时,T1再次执行相同的查询操作,会发现数据发生了变化,name字段由「王刚蛋」变成了「蝉沐风」。

如果一个事务读到了另一个已提交事务修改过的(或者是删除的)数据,而导致了前后两次读取的数据不一致的情况,这种事务并发问题叫做 不可重复读

2.3. 脏读

事情还没结束,假设T1T2都要访问user_innodb表中id1的数据,不同的是T1先读取数据,紧接着T2修改了数据的name字段,需要注意的是,T2并没有提交!

图片

此时,T1再次执行相同的查询操作,会发现数据发生了变化,name字段由「王刚蛋」变成了「蝉沐风」。

如果一个事务读到了另一个未提交事务修改过的数据,而导致了前后两次读取的数据不一致的情况,这种事务并发问题叫做 脏读

2.4. 锁与MVCC的关系

总结一下:我们在读—写,写—读的情况下会遇到3种读不一致性的问题,脏读、不可重复读以及幻读。

那写—写呢?很显然,在不做任何措施的情况下,并发会出现更大的问题。那该怎么办呢?

一切的并发问题都可以通过串行化解决,但是串行化效率太低了!

再优化一下,一切并发问题都可以通过加锁来解决,这种方案我们称为 基于锁的并发控制Lock Bases Concurrency Control , LBCC )!但是在读多写少的环境下,客户端连读取几条记录都需要排队,效率还是太低了!

因此,MySQL的设计者为事务之间的隔离性提供了不同的级别,使得开发者可以根据自己的业务场景设置不同的隔离级别,来解决(或者部分解决)读—写/写—读下的读一致性问题,而不是一上来就加锁。

这种机制叫做MVCC,如果你对这个概念不是很了解,我建议你暂停一下,读一下我的事务的隔离性与MVCC这篇文章,写得贼好!!(自卖自夸一下)

那有了MVCC是不是在读—写/写—读的情况下就不需要锁了呢?那也不是。

MVCC解决的是读—写/写—读中“ 比较纯粹的读 ”遇到的一致性问题,原谅我,这是我自己编的词儿。那什么是不纯粹的?拿存款业务举个例子。

假设陀螺要存一笔钱,系统需要先把陀螺的余额读出来,然后在余额的基础上加上本次存款的金额,最后再写入到数据库中。在将余额读出来之后,如果不想让其他事务继续访问该余额,直到整个存款事务完成之后,其他事务才可以对该余额继续进行操作,这种情况下就必须为余额的读取操作添加锁。

再总结一下: MVCC是MySQL默认的解决读—写/写—读下一致性问题的方式,不需要加锁。而锁是实现一致性的最终兜底方案,在某些特殊场景下,锁的使用不可避免

说得更准确一点,MVCC是MySQL在READ COMMITTEDREPEATABLE READ这两种隔离级别之下执行普通SELECT操作时默认解决一致性问题的方式。

具体为什么只是这两种隔离级别,建议你看看事务的隔离性与MVCC

2.5. 锁与事务的关系

事务是多个操作的集合,比如我们可以把「把大象装冰箱」这件事情作为一个事务。

图片

事务有A(原子性)、C(一致性)、I(隔离性)、D(持久性)4大特性,而锁就是实现隔离性的其中一种方案(比如还有MVCC等方案)。

事务的隔离性针对不同场景需求又实现了不同的隔离级别,不同的隔离级别下,事务使用锁的方式又会有所不同。举个例子。

READ COMMITTEDREPEATABLE READ这两种隔离级别之下,SELECT操作是不需要加锁的,直接使用MVCC机制即可满足当前隔离级别的需求。但是在SERIALIZABLE隔离级别,并且在禁用自动提交时(autocommit=0),MySQL会将普通的SELECT语句转化为SELECT ... LOCK IN SHARE MODE这样的加锁语句,如果你看不懂这句话也没关系,你只需要知道MySQL自动加锁了就行,更详细的下文再说。

另外,一个事务可能会加很多个锁,但是某个锁一定只属于一个事务。这就好比一个管理员可以管理多个保险柜,一个保险柜一定只被一个管理员管理。

3. 写—写情况

写—写的情况下肯定要加锁的了,所以接下来终于要聊一聊锁了。

我们首先研究一下锁住的东西的大小,也就是锁的粒度。

4. 锁的粒度

举一个非常应景的例子。疫情防控的时候,是封锁整个小区还是封锁某栋楼的某个单元,这完全是两种概念。

对应到MySQL锁的粒度,那就是表锁行锁

很容易想到,封锁小区的行为远比封锁某栋楼某单元的行为粗旷,因此,

从锁定粒度上来看,表锁 > 行锁

直接堵住小区的门口要比进入小区找到具体某栋楼的某个单元要快不少,因此,

从加锁效率上来看,表锁 > 行锁

直接锁住小区大概率会影响其他楼居民的正常生活和各种社会活动的开展,而锁住某栋楼某单元顶多影响这一个单元的居民的生活,因此,

从冲突概率来看,表锁 > 行锁

从并发性能来看,表锁 < 行锁

MySQL支持很多存储引擎,而不同的存储引擎对锁的支持也不尽相同。对于MyISAMMERGEMEMORY这些存储引擎而言,只支持表锁;而InnoDB存储引擎既支持表锁也支持行锁,下文讨论的所有内容均针对InnoDB存储引擎。

说完锁的粒度,还有一件事情需要我们仔细考虑一下。上文说过,READ COMMITTEDREPEATABLE READ这两种隔离级别之下,SELECT操作默认采用MVCC机制就可以了,压根儿不需要加锁,那么问题来了,万一我就是想加锁呢?

你可能会说,“简单啊,那就加锁!把数据锁死!除了我谁也别动!”

很好,但是对于大部分读—读而言,由于不会出现读一致性问题,所以不让其他事务进行读操作并不合理。

你可能又说,“那行吧,那就让读操作加锁的时候允许其他事务对锁住的数据进行读操作,但是不允许写操作。”

嗯,想得确实更细致了一些。但是再想想我上文中举过的陀螺存钱的例子,有时候SELECT操作需要独占数据,其他事务既不能读,更不能写。

我们把这种共享排他的性质称为锁的基本模式。

5. 锁的基本模式

5.1. 共享锁

共享锁(Shared Lock),简称S锁,可以同时被多个事务共享,也就是说,如果一个事务给某个数据资源添加了S锁,其他事务也被允许获取该数据资源的S锁。

由于S锁通常被用于读取数据,因此也被称为 读锁

那怎么给数据添加S锁呢?

我们可以用 SELECT ... LOCK IN SHARE MODE;的方式,在读取数据之前就为数据添加一把S锁。如果当前事务执行了该语句,那么会为读取到的记录添加S锁,同时其他事务也可以使用SELECT ... LOCK IN SHARE MODE;方式继续获取这些数据的S锁。

我们通过以下的例子验证一下S锁是否可以重复获取。

图片

5.2. 排他锁

排他锁(Exclusive Lock),简称X锁。只要一个事务获取了某数据资源的X锁,其他的事务就不能再获取该数据的X锁和S锁。

由于X锁通常被用于修改数据,因此也被称为 写锁

X锁的添加方式有两种,

  1. 自动添加X
    我们对记录进行增删改时,通常情况下会自动对其添加X锁。
  2. 手动加锁
    我们可以用 SELECT ... FOR UPDATE;的方式,在读取数据之前就为数据添加一把X锁。如果当前事务执行了该语句,那么会为读取到的记录添加X锁,这样既不允许其他事务获取这些记录的S锁,也不允许获取这些记录的X锁。

我们用下面的例子验证一下X锁的排他性。

图片

通常情况下,事务提交或结束事务时,锁会被释放。

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

    关注

    19

    文章

    7494

    浏览量

    87935
  • MySQL
    +关注

    关注

    1

    文章

    809

    浏览量

    26559
  • MVCC
    +关注

    关注

    0

    文章

    13

    浏览量

    1465
收藏 人收藏

    评论

    相关推荐

    基于MySQL机制

    在数据库系统中,为了保证数据的致性和并发控制,机制发挥着至关重要的作用。尤其在关系型数据库MySQL中,其独特的机制设计更是赢得了许多开发者的喜爱。 本文将详细探讨
    的头像 发表于 09-30 11:16 881次阅读

    redis分布式场景实现

    今天带大家深入剖析下Redis分布式彻底搞懂它。 场景 既然要搞懂Redis分布式,那肯
    的头像 发表于 09-25 17:09 722次阅读

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

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

    InnoDB的特点和状态查询

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

    读懂eMMC究竟

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

    360为什么会入局智能市场

    很难界定智能究竟属于哪个行业?智能是五金门锁行业、安防行业、家居行业和产业互联网行业的交汇产物。硬件是基础,安防及家居是应用,网络是消费渠道及用户交互界面,物联网让智能
    发表于 11-05 15:21 1498次阅读

    详细介绍MySQL InnoDB存储引擎各种不同类型的

    T1执行时,需要获取i=1的行的X(不需要获取t1表的意向了);T2执行时,需要获取t1表的
    的头像 发表于 02-20 11:12 7645次阅读
    详细介绍<b class='flag-5'>MySQL</b> InnoDB存储引擎各种不同类型的<b class='flag-5'>锁</b>

    彻底搞懂PID到底是

    先来彻底搞懂PID到底是? PID,就是比例(proportional)、积分(integral)、微分(differential),是种很常见的控制算法。在工程实际中,应用最为广
    的头像 发表于 11-13 18:21 2.5w次阅读

    数据库的机制真正的原理

    问候选人,你知道MySQL Innodb的,到底的是什么吗?关于这个问题的回答,听到过很多种,但是很少有人可以把他回答的很完美。因为想要回答好这个问题,需要对数据库的隔离级别、索引等都有
    的头像 发表于 11-12 09:33 2271次阅读

    说说MySQL有哪些

    增加自增为 innodb_autoinc_lock_mode = 2 模式时,为什么主从环境会有不安全问题的说明
    的头像 发表于 10-24 10:15 870次阅读

    MySQL是怎么加行级的?有什么规则?

    是不是很多人都对 MySQL 加行级的规则搞的迷迷糊糊,对记录会加的是 next-key 会加是间隙
    的头像 发表于 11-17 09:28 812次阅读

    彻底搞懂MySQL究竟2

    MySQL系列文章已经鸽了挺久了,最近赶紧挤了挤时间,和大家聊MySQL。 只要学计算机,「`
    的头像 发表于 03-03 10:13 437次阅读
    <b class='flag-5'>一</b><b class='flag-5'>文</b><b class='flag-5'>彻底</b><b class='flag-5'>搞懂</b><b class='flag-5'>MySQL</b><b class='flag-5'>锁</b><b class='flag-5'>究竟</b><b class='flag-5'>锁</b>的<b class='flag-5'>啥</b>2

    Linux互斥的作用 互斥是什么

    1、互斥 互斥(mutex),在访问共享资源之前对互斥进行上锁,在访问完成后释放互斥(解锁);对互斥
    的头像 发表于 07-21 11:13 940次阅读

    自旋和互斥的区别有哪些

    自旋 自旋与互斥很相似,在访问共享资源之前对自旋进行上锁,在访问完成后释放自旋(解锁);事实上,从实现方式上来说,互斥
    的头像 发表于 07-21 11:19 9493次阅读

    互斥和自旋的实现原理

    互斥和自旋是操作系统中常用的同步机制,用于控制对共享资源的访问,以避免多个线程或进程同时访问同资源,从而引发数据不致或竞争条件等问题。 互斥
    的头像 发表于 07-10 10:07 495次阅读