![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=1738956157-XPi2FTQFhzdFef9flsVXYS1yMBNllcGB-0-def791b56c2c565ab3aa7299281cc36d)
需要注意的是,这里的共享锁和排他锁都是表级别锁。
接下来用一个案例来说明共享锁的作用。
准备的环境如下:
![](https://epubservercos.yuewen.com/0B7DFA/26763970301523506/epubprivate/OEBPS/Images/43605_38_2.jpg?sign=1738956157-aUixqcwHuP2ba6DKzeBfQh7M0QPCwm0u-0-0ffd94db9a2d1de1e0caa774880811e5)
事务A执行如下语句:
![](https://epubservercos.yuewen.com/0B7DFA/26763970301523506/epubprivate/OEBPS/Images/43605_38_3.jpg?sign=1738956157-kqWQuoXtcW3BWICqnEOK1VWHQIczyuh4-0-87f748e98f26f59e71ef86844603b2f8)
事务A会在表t上加意向排他锁,并在id=10这行数据上加行级别排他锁。
事务B执行如下语句:
![](https://epubservercos.yuewen.com/0B7DFA/26763970301523506/epubprivate/OEBPS/Images/43605_38_4.jpg?sign=1738956157-hsw0BKVWzabMp1rEd53StdFI1aWR9wBa-0-fc8fc88ce071f1dc239f8f40085f3259)
检测到事务A已经在表t上添加了意向排他锁且未释放,此时事务B将处于阻塞状态。
从上面的案例中不难发现,如果存在意向锁,事务B就不需要检查表t的每行是否存在排他锁,这可以提高事务效率。但是可能有人会问,为什么不直接加一个表级别锁呢?提到这个问题就不得不讨论意向锁的并发性了。
前面的定义中提到了,意向锁之间是相互兼容的,并且意向锁是不会和行级别锁发生冲突的表级别锁。正是由于这个特性,意向锁不会对多个事务不同数据行的加锁产生影响,也就不会影响事务的并发性。下面通过一个案例进行详细的介绍。
事务A执行如下语句:
![](https://epubservercos.yuewen.com/0B7DFA/26763970301523506/epubprivate/OEBPS/Images/43605_38_5.jpg?sign=1738956157-TarPQheb5EadFfCYrccLiOSC1xqKcR7G-0-46e3b0ecf3f455f7a53863719adf0e97)
事务A会在表t上加意向排他锁,并在id=11这行数据上加行级别排他锁。
事务B执行如下语句:
![](https://epubservercos.yuewen.com/0B7DFA/26763970301523506/epubprivate/OEBPS/Images/43605_39_1.jpg?sign=1738956157-27HulEqSQPJkFSwFxUOyzYR0G9QAzGxD-0-175ecee83aa3251617111afc773e23cd)
事务B会在表t上加意向排他锁,并在id=12这行数据上加行级别排他锁。
由上面这个案例可以看出,事务A和事务B都在表t上加了意向排他锁,但由于意向锁的特性(如果事务A上加的不是意向锁而是表级别锁,那么事务B将会被阻塞),这两个事务加锁都不会受到影响。