一、介绍
为了避免DML在执行时,加的行锁与表锁的冲突,在InnoDB中引入了意向锁,使得表锁不用检查每行数据是否加锁,使用意向锁来减少表锁的检查。
有一个客户端,它要去操作这张表,先开启事务,然后执行update语句,在更新的时候,就要更新这张表中id为3的这条记录,那么此时在默认的MySQL的隔离级别之下,你执行这条update语句,并且还是根据主键进行更新,它会自动的对这一行加上行锁。
假如没有意向锁,客户端一对表加了行锁后,客户端二如何给表加表锁呢,来通过示意图简单分析一下:
首先客户端一,开启一个事务,然后执行DML操作,在执行DML语句时,会对涉及到的行加行锁。
当客户端二,想对这张表加表锁时,会检查当前表是否有对应的行锁,如果没有,则添加表锁,此时就会从第一行数据,检查到最后一行数据,效率较低。
有了意向锁之后 :为了解决我们在执行DML语句的时候所加的行锁以及表锁的冲突,在InnoDB引擎中就加入了意向锁,加入了意向锁就使得表锁在检查的时候不用去检查每一行数据是否加锁,我们直接使用意向锁来减少表锁的检查,从而提高性能。
客户端一,在执行DML操作时,会对涉及的行加行锁,同时也会对该表加上意向锁。
而其他客户端,在对这张表加表锁的时候,会根据该表上所加的意向锁来判定是否可以成功加表锁,而不用逐行判断行锁情况了。
如果这张表的意向锁和当前所加的表锁是兼容的,那就直接加锁;如果说当前的意向锁和所要加的表锁是不兼容的,那么此时在这一块就会处于阻塞状态,阻塞到左侧,即线程A这一块的事物提交,行锁、意向锁释放后,它就会解除阻塞状态,拿到这张表的表锁。
二、分类
- 意向共享锁(IS): 由语句
select ... lock in share mode
添加 。 与表锁共享锁 (read)兼容,与表锁排他锁(write)互斥。 - 意向排他锁(IX): 由
insert、update、delete、select...for update
添加 。与表锁共享锁(read)及排他锁(write)都互斥,意向锁之间不会互斥。
一旦事务提交了,意向共享锁、意向排他锁,都会自动释放。
可以通过以下SQL,查看意向锁及行锁的加锁情况:
这条SQL和我们刚刚讲解元数据锁所对应的表不是一张表。元数据锁它查询的表是 metadata_locks
,而这一块我们要操作的表是 data_locks
。
select object_schema,object_name,index_name,lock_type,lock_mode,lock_data from performance_schema.data_locks;