本文正在参加「技术专题19期 漫谈数据库技术」活动
一、意图锁(Intention Locks)是什么
本文谈到的意图锁是Mysql Innodb存储引擎中的概念。
想理解好"意图锁"的概念,要将这个词拆成两部分, 一部分是"意图", 一部分是"锁"。
首先这个"锁"是表级别的锁, 那么谈论锁的兼容性时,就只谈论与其它表级锁的兼容性, 也就是说意图锁与行级别的锁并没有竞争关系。
再看"意图"的含义,是什么意图呢?其实是加行级锁的意图,即表示有事务将要申请行级锁。
行级锁有两种类型,分别是共享锁(shared lock) 和排他锁(exclusive lock), 相应的意图锁根据申请行级锁类型的不同也分为了意图共享锁(intention shared lock) 和意图排他锁(intention exclusive lock) 两类。
那么就比较有意思了,意图锁本身是表级锁,但体现的意图却是要申请行级锁。它的作用是什么呢?
二、意图锁的作用
Mysql是支持表级锁和行级锁混合使用的。
intention lock的主要作用是通过表明表上是否存在行级锁以减少锁表时的性能消耗。
无论是以shared还是exclusive的方式锁表,都需要知道该表上是否存在行级锁。
表锁在锁表时如何得知行锁的情况呢?如无其它条件辅助需要遍历索引才能得知,遍历操作带来的性能消耗是不容忽视的。
因此增加了intention Lock的概念,事务在加行级锁之前先加表级的意图锁,其它事务能以较小的代价得知某张表有行正在被锁定。
三、意图锁的兼容性
意图锁既然是表级锁, 谈论兼容性时只谈论与其它表级锁的兼容性, 下表中的S和X分别代表表级共享锁和表级排他锁, IS和IX分别代表意图共享锁和意图排他锁。
| IX | IS | X | S | |
|---|---|---|---|---|
| IX | 兼容 | 兼容 | 互斥 | 互斥 |
| IS | 兼容 | 兼容 | 互斥 | 兼容 |
| X | 互斥 | 互斥 | 互斥 | 互斥 |
| S | 互斥 | 兼容 | 互斥 | 兼容 |
这个兼容性关系如何理解和记忆呢?先看左上角区域的格子,特别要注意的是IS和IX之间是互相兼容的,没有任何互斥关系。从实际加锁的场景来理解会更容易记忆:
-
设想有一张表t,事务A要修改表t的第m行,将在m行加行级排他锁mRX。
-
事务A要先表明加mRX的意图, 即先加IX锁。
-
在加IX锁之前要先检查兼容性。IX的意图是要加独占的行级锁mRX,所以无论是共享的表级锁S还是独占的表级锁X与IX都是互斥的。
-
假设事务A发现无冲突并成功申请了IX锁(说明此时表t没有S、X这两种表锁存在)。
-
此时事务B要要修改表t的第n行, 将在第n行加行级排他锁nRX。
-
按照规则事务B在加行级独占锁nRX之前,也要表明意图,事务B也要申请IX锁。
-
重点来了,此时事务A已经申请了IX,事务B也要申请IX,此时该发生冲突吗? 不应该。mRX和nRX是针对不同行的排他锁,mRX和nRX两者是兼容的,那mRX和nRX的"意图"也应该是兼容的。
理解了IX与IX的兼容性, IS与IX、IS与IS为什么都是互相兼容的就很容易理解了。
再看IS、IX与S、X的兼容性, 同样用"意图"表明的"实际行为"去理解会更容易。
-
IS是行级共享锁的意图, 行级共享锁与表级共享锁S应该是兼容的, 与表级排他X应该是互斥的。
-
IX是行级排他锁的意图, 行级排他锁无论与表级共享锁S还是表级排他锁X都应该是互斥的。
四、一些总结与思考
意图锁概念的提出虽然提升了系统的复杂度,但是带来的好处还是很明显的。程序开发中这种利弊权衡随处可见,虽然追求简洁但经常不得不创造或引入新的概念。
概念的创造或引入要尽量优雅、自然,“意图锁”之"意图"就是个不错的例子。
类似"表级锁"、"行级锁"两个不同级别的东西要混合在一起使用时,常常带来一些麻烦于混乱。
为了规避这种不同级别概念混用带来的麻烦与混乱,将更细粒度的东西包裹一层,使它"膨胀"到与粗粒度同一级别, 是不是通常都行之有效呢?遇到类似的问题时或许可以用类似的思路去尝试解决。
本文正在参加「技术专题19期 漫谈数据库技术」活动