
3.2 意向锁
InnoDB支持多粒度锁(Multiple Granularity Locking),并且允许行级别锁和表级别锁共存,而意向锁就是表级别锁中的一种。
需要强调的是,意向锁是一种不会和行级别锁发生冲突的表级别锁。其中,意向锁分为以下两种。
● 意向共享(IS)锁:事务在对表中的某些行加共享锁前必须先获得该表的意向共享锁。
● 意向排他(IX)锁:事务在对表中的某些行加排他锁前必须先获得该表的意向排他锁。
意向锁主要解决如下问题:当一个事务想要在表A上添加表级别共享锁或排他锁时,不需要检查表A上的行锁,而是检查表A上的意向锁,如果互斥则阻塞事务。
意向锁的兼容性如表3-1所示。
表3-1 意向锁的兼容性

需要注意的是,这里的共享锁和排他锁都是表级别锁。
接下来用一个案例来说明共享锁的作用。
准备的环境如下:

事务A执行如下语句:

事务A会在表t上加意向排他锁,并在id=10这行数据上加行级别排他锁。
事务B执行如下语句:

检测到事务A已经在表t上添加了意向排他锁且未释放,此时事务B将处于阻塞状态。
从上面的案例中不难发现,如果存在意向锁,事务B就不需要检查表t的每行是否存在排他锁,这可以提高事务效率。但是可能有人会问,为什么不直接加一个表级别锁呢?提到这个问题就不得不讨论意向锁的并发性了。
前面的定义中提到了,意向锁之间是相互兼容的,并且意向锁是不会和行级别锁发生冲突的表级别锁。正是由于这个特性,意向锁不会对多个事务不同数据行的加锁产生影响,也就不会影响事务的并发性。下面通过一个案例进行详细的介绍。
事务A执行如下语句:

事务A会在表t上加意向排他锁,并在id=11这行数据上加行级别排他锁。
事务B执行如下语句:

事务B会在表t上加意向排他锁,并在id=12这行数据上加行级别排他锁。
由上面这个案例可以看出,事务A和事务B都在表t上加了意向排他锁,但由于意向锁的特性(如果事务A上加的不是意向锁而是表级别锁,那么事务B将会被阻塞),这两个事务加锁都不会受到影响。