前言MySQL 作为使用范围最广的开源关系型数据库,是每个后端开发人员都绕不开的一道坎 。我在上一篇文章中也写了关于 MySQL 中的 MVCC 的细节及各个隔离级别如何使用 MVCC,有兴趣的可以查看 。
这一篇文章则是跟 MySQL 中的锁有关,锁是在并发程序中最经常使用的手段之一,但是锁的滥用也会给程序的性能带来极大的负担 。而我们平时使用 MySQL 做增删改查操作的时候,感觉不到我们有在使用锁,实际上是因为 MySQL 已经为我们使用了相关的锁 。如果你想知道我们平时使用的 SQL 语句都使用了哪些锁?都是怎么加锁的?这些锁的作用是什么?那么可以继续往下看 。
文章插图
普通锁InnoDB 实现了标准行级锁,而行级锁有两种类型:
- 共享锁(shared lock,以下将会简称为 S 锁):意在共享 。也就是允许多个事务共同持有一个记录的共享锁,该锁主要用于读取操作 。
- 排他锁(exclusive lock,以下将会简称为 X 锁):意在排斥 。只能允许一个事务持有一个记录的排他锁,该锁主要用于更新和删除操作 。
如果有一个事务 T1 持有行 r 的 S 锁,并且同时有另一个事务 T2 想要获取行 r 中的锁,T2 获取不同的锁将会有如下的情况发生:
- 假如 T2 想要获取行 r 的 S 锁,那么 T2 将会立刻得到该锁 。
- 假如 T2 想要获取行 r 的 X 锁,那么 T2 则会被阻塞,直到 T1 释放了行 r 的 S 锁 。
X 锁与 S 锁的兼容性如下图所示:
文章插图
最左边是持有的锁,最上面是想要申请的锁 。从图中可以看出,只要跟 X 锁相关的,都会冲突,也就是会造成阻塞 。
意向锁InnoDB 允许多种粒度的锁共存,所以会有表锁和行锁共存的情况 。为了让多种粒度的锁可以共存,InnoDB 使用了意向锁 。意向锁是表级锁,它是为了表明有一个事务正在持有锁或者打算申请一个锁 。
意向锁有两种类型:
- 共享意向锁(intention shared lock,以下简称 IS):表示事务持有表中行的共享锁或者打算获取行的共享锁 。
- 共享排他锁(intention exclusive lock,以下简称 IX):表示事务持有表中行的排他锁或者打算获取行的排他锁 。
意向锁的使用规则如下:
- 事务在获取表中的共享行锁时,需要先获取表中的 IS 锁或者等级更高的锁 。
- 事务在获取表中的排他行锁时,需要先获取表中的 IX 锁 。
表级别下的X锁、S锁、IS 锁和 IX 锁的兼容性如下:
文章插图
注意:这里的 X 锁、S 锁说的也是表级锁,不要理所当然的想成了行级锁 。
为什么会有意向锁的出现呢?我们考虑如下场景(假设不存在意向锁):
一个事务 A 想要修改表 t 中的行 r,所以 A 获取行 r 的 X 锁,事r务 A 现在持有一个行锁 。此时,有一个事务 B 想要使用 ALTER TABLE 语句修改表 t 的结构,该语句首先需要获取表 t 的 X 锁,但是此时事务 B 并不知道表中是否有行被锁住,所以它只能一行一行去遍历,然后把遍历的行也锁住,直到发现表中没有行在之前已经被锁住,现在它就可以修改表的结构了 。但是它发现表中已经存在一些行被锁住,那么它就不能修改表结构,需要等这些锁都释放 。
文章插图
这里有一个大问题,最坏的情况下,需要遍历所有的行才能知道是否有行被锁住,这是非常消耗性能的,而意向锁就可以解决这个问题 。我们现在再来考虑相同场景下,意向锁如何解决这个问题:
一个事务 A 想要修改表 t 中的行 r,A 首先需要获取表 t 的 IX 锁,然后成功获取 IX 锁之后,再去申请行 r 的 X 锁,申请成功之后,事务 A 此时就持有两个锁,分别是表 t 的 IX 锁和行 r 的 X 锁 。此时,有一个事务 B 想要使用 ALTER TABLE 语句修改表 t 的结构,该语句需要获取表 t 的 X 锁,事务 B 可以查看表 t 上是否存在锁来判断表中的行是否被上锁,当发现表 t 上存在 IX 锁,事务 B 就会被阻塞,因为它知道表中已经有行被锁定,所以无法申请到表 t 的 X 锁 。
推荐阅读
- 雷电3的大用处!1小时解决旧Mac电脑数据迁移
- Mac电脑上如何找到你的“任务管理器”
- Kbone原理详解与小程序技术选型
- 如何解决路由器静态IP+PPPoE拨号双链路负载分担问题
- 古代所说的“促织”是指现在的什么?
- 阖家幸福和合家幸福有什么区别?
- 太阳能|不烧油不充电 “天津号”太阳能汽车亮相 :真“环保”
- 如何提升店铺等级 如何快速提升淘宝店等级
- 茶具不抽水怎么解决,新紫砂茶具怎么使用
- 聪明女人“三不管” 才能“管”住男人