【搞定面试之mysql】第三篇 mysql的锁

目录

​编辑

前言:

全局锁

表级锁

表锁

元数据锁

意向锁

行级锁

总结


前言:

锁这个词语大家都不陌生吧,在并发的情况下,它可谓是神通广大,没有它那我们对于许多软件,网站的使用体验就会大打折扣,今天我们一起学习mysql的锁,来探究大名鼎鼎的mysql数据库是如何保证并发安全的。

全局锁

介绍

全局锁就是对整个数据库实例加锁,加锁后整个实例就处于只读状态,后续的DML的写语句,DDL语句,已经更新操作的事务提交语句都将被阻塞。

其典型的使用场景是做全库的逻辑备份,对所有的表进行锁定,从而获取一致性视图,保证数据的完整性。

● 特点

数据库中加全局锁,是一个比较重的操作,存在以下问题:

1.如果在主库上备份,那么在备份期间都不能执行更新,业务基本上就得停摆。

2.如果在从库上备份,那么在备份期间从库不能执行主库同步过来的二进制日志(binlog),会导致主从延迟。

在InnoDB引擎中,我们可以在备份时加上参数-single-transaction参数来完成不加锁的一致性数据备份。

表级锁

介绍

表级锁,每次操作锁住整张表。锁定粒度大,发生锁冲突的概率最高,并发度最低。应用在MyISAM、InnoDB、BDB等存储引擎中。

对于表级锁,主要分为以下三类:
1.表锁
2.元数据锁
3. 意向锁

表锁

一句话:读锁大家都只能读,写锁就只有本客户端能写能读。

元数据锁

元数据锁 是 MySQL 用来保护表结构 的一种表级锁 。它的核心作用就一句话:防止在事务执行过程中,表结构被其他线程修改

如果没有 MDL,可能会出现这种灾难:一个事务正在查询某张表,另一个事务同时执行 ALTER TABLE 把字段删了,导致查询线程读到错误的数据结构,甚至崩溃。

  • 读锁:当有事务对表进行 DML(增删改查)时,会自动获得 MDL 读锁。多个事务可以同时持有读锁。

  • 写锁:当执行 DDL (如 ALTER TABLEDROP TABLE)时,需要 MDL 写锁。写锁与任何读锁都不兼容,所以必须等待所有持有读锁的事务结束后才能执行。

加锁时机 :MySQL 在事务开始访问表 时加 MDL,在事务提交或回滚时释放。

意向锁

意向锁是表级锁,由InnoDB自动维护,分为意向共享锁(IS)和意向排他锁(IX)。

作用 :当另一个事务想加表锁时,不需要遍历每一行检查是否有行锁,直接看意向锁就知道------快速判断表里是否有行锁,提高锁冲突检测效率。

  • 有了 意向共享锁(IS) → 可以再加 表级共享锁(S) ,但不能加 表级排他锁(X)

  • 有了 意向排他锁(IX)不能加任何表锁(S 或 X 都不行)。

比如事务 A 持有 IX 锁,事务 B 执行 LOCK TABLES t READ就会失败因为这样加了表级共享锁(S)

  • 意向锁之间互相兼容,不影响其他事务加意向锁。

可以简单的理解

共享锁:就是读锁的意思,然后都只能读

排他锁:就是写锁的意思,然后自己能读能写,别人啥都干不了

行级锁

介绍

行级锁,每次操作锁住对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在InnoDB存储引擎中。

假设有一个 id 索引,已有的数据是:1, 5, 10

  • 行锁 :锁住某一行,比如 id=5

  • 间隙锁 :锁住记录之间的空隙,比如 (1,5) 表示大于1且小于5的范围,不包含1和5

临键锁 = 记录锁 + 间隙锁,它锁的是一个"左开右闭"的区间。

比如临键锁 (1,5] 的含义是:锁住 大于1 且 小于等于5 的范围。

  • 左边是"开",不包含1。

  • 右边是"闭",包含5。

所以当事务对 id=5 这条记录加临键锁时,实际锁住的是 (1,5] 这个区间,即:

  • 禁止其他事务插入 id 在 (1,5) 之间的值(如2,3,4)

  • 同时禁止其他事务修改或删除 id=5 这行

临键锁的设计初衷是 防止幻读锁定当前记录

共享锁:只能读这行 不能修改这行,获取排他锁也就是进行写操作。

排他锁:其他事务啥都不能干。

行锁类型为排他锁:表示在进行这些操作时,其他事务啥都不能干

为共享锁:其他事务可以读

默认情况下,InnoDB在REPEATABLE READ事务隔离级别运行,InnoDB使用next-key锁进行搜索和索引扫描,以防止幻读。

1.针对唯一索引进行检索时,对已存在的记录进行等值匹配时,将会自动优化为行锁。

就是当你用唯一索引比如id=5,肯定就只能查到id=5的数据,**临键锁是行锁+间隙锁,因为只有一条所以不可能发生幻读,所以就不用间隙锁,**将会自动优化为行锁。前提是能查到。

2.InnoDB的行锁是针对于索引加的锁不通过索引条件检索数据或者索引失效,那么InnoDB将对表中的所有记录加锁,此时就会行锁升级为表锁

我来解释一下

1:

比如表里 id 有 1、5、10,你执行
SELECT * FROM t WHERE id = 8 FOR UPDATE(8 不存在)。

  • 不会锁任何一行,而是锁住 5 和 10 之间的间隙 (5,10)

  • 作用:禁止别人插入 8,防止幻读。

2:比如普通索引 age,有 1、2、2、5。你执行
SELECT * FROM t WHERE age = 2 FOR UPDATE

  • 会锁住所有 age=2 的行,同时锁住 age=2 到下一个值(5)之间的间隙。

  • 因为普通索引不唯一,必须防止别人插入另一个 age=2,所以间隙要锁到下一个不同的值为止。

3:

比如主键 id,你执行
SELECT * FROM t WHERE id > 5 FOR UPDATE

  • 会锁住 id 从 6 开始的所有行,并且一直锁到最大值。

  • 如果中途遇到一个不满足条件的值(比如 id=10 是最大值,再往后没有),就只锁到最大值。

  • 但如果是 id >= 5,就会锁住 5 以及后面的所有行,直到最后。

总结

在进行学习的时候一定要构建知识网络,索引,锁,mvcc,事务他们都是有关联的,因为事务隔离性所以来了锁和mvcc,索引也会影响锁,比如没索引行锁变表锁,都是有关联的,内容确实多,但是把他们联系起来然后多看几遍我相信你的收获一定不小。

相关推荐
RuoyiOffice2 小时前
企业请假销假系统设计实战:一张表、一套流程、两段生命周期——BPM节点驱动的表单变形术
java·spring·uni-app·vue·产品运营·ruoyi·anti-design-vue
鹤旗2 小时前
While语句,do-while语句,for语句
java·jvm·算法
NAGNIP2 小时前
一文搞懂卷积神经网络经典架构-LeNet
算法·面试
小碗羊肉2 小时前
【从零开始学Java | 第十八篇】BigInteger
java·开发语言·新手入门
NAGNIP2 小时前
一文搞懂深度学习中的池化!
算法·面试
sky wide2 小时前
[特殊字符] Docker Swarm 集群搭建指南
java·docker·容器
wuqingshun3141592 小时前
谈谈你对springAop动态代理的理解?
java·jvm
执笔画流年呀2 小时前
PriorityQueue(堆)续集
java·开发语言
武超杰2 小时前
Spring Boot入门教程
java·spring boot·后端