欢迎来到Introzo百科
Introzo百科
【299期】面试官:详细说一说MySQL InnoDB 中意向锁的作用
2022年5月17日 下午4:11
•
面试题 •
阅读 9
前言
InnoDB 支持多粒度锁(multiple granularity locking),它允许行级锁与表级锁共存,而意向锁就是其中的一种表锁。
意向锁(Intention Locks)
需要强调一下,意向锁是一种不与行级锁冲突表级锁,这一点非常重要。意向锁分为两种:
意向共享锁(intention shared lock, IS):事务有意向对表中的某些行加共享锁(S锁)
-- 事务要获取某些行的 S 锁,必须先获得表的 IS 锁。SELECT column FROM table ... LOCK IN SHARE MODE;
意向排他锁(intention exclusive lock, IX):事务有意向对表中的某些行加排他锁(X锁)
-- 事务要获取某些行的 X 锁,必须先获得表的 IX 锁。SELECT column FROM table ... FOR UPDATE;
即:意向锁是有数据引擎自己维护的,用户无法手动操作意向锁,在为数据行加共享 / 排他锁之前,InooDB 会先获取该数据行所在在数据表的对应意向锁。
意向锁要解决的问题
我们先来看一下百度百科上对意向锁存在意义的描述:
如果另一个任务试图在该表级别上应用共享或排它锁,则受到由第一个任务控制的表级别意向锁的阻塞。第二个任务在锁定该表前不必检查各个页或行锁,而只需检查表上的意向锁。
设想这样一张 users 表:MySQL,InnoDB,Repeatable-Read:users(id PK,name)
事务 A 获取了某一行的排他锁,并未提交:
SELECT * FROM users WHERE id = 6 FOR UPDATE;
事务 B 想要获取 users 表的表锁:
LOCK TABLES users READ;
因为共享锁与排他锁互斥,所以事务 B 在视图对 users 表加共享锁的时候,必须保证:
当前没有其他事务持有 users 表的排他锁。
当前没有其他事务持有 users 表中任意一行的排他锁 。
为了检测是否满足第二个条件,事务 B 必须在确保 users表不存在任何排他锁的前提下,去检测表中的每一行是否存在排他锁。很明显这是一个效率很差的做法,但是有了意向锁之后,情况就不一样了:
意向锁的兼容互斥性
意向锁是怎么解决这个问题的呢?首先,我们需要知道意向锁之间的兼容互斥性:
即意向锁之间是互相兼容的,emmm……那你存在的意义是啥?
虽然意向锁和自家兄弟互相兼容,但是它会与普通的排他 / 共享锁互斥:
注意:这里的排他 / 共享锁指的都是表锁!!!意向锁不会与行级的共享 / 排他锁互斥!!!
现在我们回到刚才 users 表的例子:
事务 A 获取了某一行的排他锁,并未提交:
SELECT * FROM users WHERE id = 6 FOR UPDATE;
此时 users 表存在两把锁:users 表上的意向排他锁与 id 为 6 的数据行上的排他锁。
事务 B 想要获取 users 表的共享锁:
LOCK TABLES users READ;
此时事务 B 检测事务 A 持有 users 表的意向排他锁,就可以得知事务 A 必然持有该表中某些数据行的排他锁,那么事务 B 对 users 表的加锁请求就会被排斥(阻塞),而无需去检测表中的每一行数据是否存在排他锁。推荐:250期面试题
意向锁的并发性
这就牵扯到我前面多次强调的一件事情:
意向锁不会与行级的共享 / 排他锁互斥!!!意向锁不会与行级的共享 / 排他锁互斥!!!意向锁不会与行级的共享 / 排他锁互斥!!!
重要的话要加粗说三遍,正因为如此,意向锁并不会影响到多个事务对不同数据行加排他锁时的并发性(不然我们直接用普通的表锁就行了)。推荐:250期面试题
最后我们扩展一下上面 users 表的例子来概括一下意向锁的作用(一条数据从被锁定到被释放的过程中,可能存在多种不同锁,但是这里我们只着重表现意向锁):
事务 A 先获取了某一行的排他锁,并未提交:
SELECT * FROM users WHERE id = 6 FOR UPDATE;
事务 A 获取了 users 表上的意向排他锁。
事务 A 获取了 id 为 6 的数据行上的排他锁。
之后事务 B 想要获取 users 表的共享锁:
LOCK TABLES users READ;
事务 B 检测到事务 A 持有 users 表的意向排他锁。
事务 B 对 users 表的加锁请求被阻塞(排斥)。
最后事务 C 也想获取 users 表中某一行的排他锁:
SELECT * FROM users WHERE id = 5 FOR UPDATE;
事务 C 申请 users 表的意向排他锁。
事务 C 检测到事务 A 持有 users 表的意向排他锁。
因为意向锁之间并不互斥,所以事务 C 获取到了 users 表的意向排他锁。
因为id 为 5 的数据行上不存在任何排他锁,最终事务 C 成功获取到了该数据行上的排他锁。
总结
InnoDB 支持多粒度锁,特定场景下,行级锁可以与表级锁共存。
意向锁之间互不排斥,但除了 IS 与 S 兼容外,意向锁会与 共享锁 / 排他锁 互斥。
IX,IS是表级锁,不会和行级的X,S锁发生冲突。只会和表级的X,S发生冲突。
意向锁在保证并发性的前提下,实现了行锁和表锁共存且满足事务隔离性的要求。
来源:www.introzo.com/post/6844903666332368909
END
题外推荐
推荐一个“摸鱼程序员”聚集地
十期推荐
【281期】滴滴二面:try-catch-finally 和 return 是什么顺序执行的?【282期】面试官:你能说说 Nacos 的实现原理吗?【283期】熊大同学的面试回忆录(2.5年开发经验)【284期】共享锁、排他锁、互斥锁、悲观锁、乐观锁、行锁、表锁、页面锁、不可重复读、丢失修改、读脏数据【285期】Spring的@Transactional如何实现的(必考)【286期】面试时被问到Flutter/Dart的HashMap怎么办?【287期】ArrayList使用forEach遍历的时候删除元素会报错吗?【288期】面试官:什么是CAP 定理,为什么CAP不能同时被满足?【289期】面试官:说一下JVM常用垃圾回收器的特点、优劣势、使用场景和参数设置【290期】为什么不建议使用Java序列化?
与其在网上拼命找题? 不如马上关注我们~
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由半码博客整理,本文链接:https://www.introzo.com/index.php/post/8363.html
相关文章
- 10-05 总线 Linux下I2C总线的配置和使用(linu
- 10-05 Linux文件夹链接技术指南(Linux文件夹链接
- 10-05 如何导出Oracle中不涉及的表(oracle导出
- 10-05 Linux下如何查找文件中的字符串(Linux文件
- 10-05 Linux:玩的乐趣(Linux好玩吗?)
- 10-05 改进Linux内核:驱动模块的重要性(linux内
- 10-05 keil5TIM中断_keil5中断编写方法
- 10-05 vs2010中如何防止反编译_vs反编译exe
- 10-05 彻底删除vs2005_彻底删除vs2017
- 10-05 长电科技表示,已具备4nm手机芯片封装能力,以及C
- 10-05 中国信息通信研究院公布可信隐私计算评估结果, Mo
- 10-05 信通院:2022年7月国内手机出货量1990.8万
- 10-05 Numpy.frompyfunc() 将计算单个值
- 10-05 C语言·删除数组第0个元素
- 10-05 (2)NumPy库初识(数组运算和运算)
- 10-05 什么是手机副卡
- 10-05 副手机卡可以独立吗?
- 10-05 手机主卡可以查询副卡的哪些信息
- 10-05 如何修复 WINDOWS 11/10 中磁盘空间使
- 10-05 4 款最佳 Windows 11 声卡可供选择
- 最近发表