![MySQL DBA 精英实战课](https://wfqqreader-1252317822.image.myqcloud.com/cover/623/47379623/b_47379623.jpg)
3.2 意向锁
InnoDB支持多粒度锁(Multiple Granularity Locking),并且允许行级别锁和表级别锁共存,而意向锁就是表级别锁中的一种。
需要强调的是,意向锁是一种不会和行级别锁发生冲突的表级别锁。其中,意向锁分为以下两种。
● 意向共享(IS)锁:事务在对表中的某些行加共享锁前必须先获得该表的意向共享锁。
● 意向排他(IX)锁:事务在对表中的某些行加排他锁前必须先获得该表的意向排他锁。
意向锁主要解决如下问题:当一个事务想要在表A上添加表级别共享锁或排他锁时,不需要检查表A上的行锁,而是检查表A上的意向锁,如果互斥则阻塞事务。
意向锁的兼容性如表3-1所示。
表3-1 意向锁的兼容性
![](https://epubservercos.yuewen.com/0B7DFA/26763970301523506/epubprivate/OEBPS/Images/43605_38_1.jpg?sign=1739323019-RA79Ss0t6ERRYKnvX4rjMqLNt79C7vef-0-3ba9273effaf9fe45f44ac553b65c25f)
需要注意的是,这里的共享锁和排他锁都是表级别锁。
接下来用一个案例来说明共享锁的作用。
准备的环境如下:
![](https://epubservercos.yuewen.com/0B7DFA/26763970301523506/epubprivate/OEBPS/Images/43605_38_2.jpg?sign=1739323019-KY4kRVQGLJqrq5cfmX3xMSdFpTj7avRu-0-799a97e8c85e30cd9ebc082305252cdb)
事务A执行如下语句:
![](https://epubservercos.yuewen.com/0B7DFA/26763970301523506/epubprivate/OEBPS/Images/43605_38_3.jpg?sign=1739323019-bYosp5JAA41tJxgDEu3V3RyaKYsXFg1j-0-89b42a5987b23c72e3fe3ef25c0bdb77)
事务A会在表t上加意向排他锁,并在id=10这行数据上加行级别排他锁。
事务B执行如下语句:
![](https://epubservercos.yuewen.com/0B7DFA/26763970301523506/epubprivate/OEBPS/Images/43605_38_4.jpg?sign=1739323019-UDxLneEoKEvKy9zjX1ppD3qL00s0M5Xf-0-8f311d7565447c3cd9ae851d86daef51)
检测到事务A已经在表t上添加了意向排他锁且未释放,此时事务B将处于阻塞状态。
从上面的案例中不难发现,如果存在意向锁,事务B就不需要检查表t的每行是否存在排他锁,这可以提高事务效率。但是可能有人会问,为什么不直接加一个表级别锁呢?提到这个问题就不得不讨论意向锁的并发性了。
前面的定义中提到了,意向锁之间是相互兼容的,并且意向锁是不会和行级别锁发生冲突的表级别锁。正是由于这个特性,意向锁不会对多个事务不同数据行的加锁产生影响,也就不会影响事务的并发性。下面通过一个案例进行详细的介绍。
事务A执行如下语句:
![](https://epubservercos.yuewen.com/0B7DFA/26763970301523506/epubprivate/OEBPS/Images/43605_38_5.jpg?sign=1739323019-f8RjeziATmzeZ2vusMR9FgQ0zjg8Bs5x-0-c568ada2020751a2de6ad0bae479cbed)
事务A会在表t上加意向排他锁,并在id=11这行数据上加行级别排他锁。
事务B执行如下语句:
![](https://epubservercos.yuewen.com/0B7DFA/26763970301523506/epubprivate/OEBPS/Images/43605_39_1.jpg?sign=1739323019-kPdYw5KbS1H5OcGVAugJiiI9xI1yqZN6-0-e44a3e53070b0301034db5860b2adc27)
事务B会在表t上加意向排他锁,并在id=12这行数据上加行级别排他锁。
由上面这个案例可以看出,事务A和事务B都在表t上加了意向排他锁,但由于意向锁的特性(如果事务A上加的不是意向锁而是表级别锁,那么事务B将会被阻塞),这两个事务加锁都不会受到影响。