0
点赞
收藏
分享

微信扫一扫

innoDB的锁的类型及加锁方法

曾宝月 2022-02-11 阅读 87

首先要明白,innoDB支持多粒度锁,即允许行锁和表锁共存

4种常见锁:

  • 共享锁(shared lock)(读锁,S锁):
    S锁分为行级S锁和表级S锁。不同的事务可以同时获得同一个S锁(即不同事务可以共享S锁),比如不同事务可以同时获取某表的某行的S锁。某表或某行被S锁锁定后,就不能被X锁锁定(即S锁和X锁是互斥的);
  • 排他锁(exclusive lock)(写锁,X锁):
    X锁分为行级X锁和表级X锁。X锁与其它一切锁都是互斥的(这就是"排他"的含义),比如某表的某行被X锁锁定后,既不能被其它事务的S锁锁定,也不能被其它事务的X锁锁定;
  • 意向共享锁(intention shared lock,IS锁):
    这个锁表明事务有意向获取某行的读锁,这是个表级锁。某个事务获取某表的行级S锁前,必须先获取该表的IS锁;
  • 意向排他锁(intention exclusive lock,IX锁):
    这个锁表明事务有意向获取某行的写锁,这是个表级锁。某个事务获取某表的行级X锁前,必须先获取该表的IX锁;

上述4中锁的表锁兼容性如下表格(注意表格中的X锁和S锁都是表级锁,不是行级锁):

XIXSIS
Xconflictconflictconflictconflict
IXconflictcompatibleconflictcompatible
Sconflictconflictcompatiblecompatible
ISconflictcompatiblecompatiblecompatible

意向锁的作用:

首先要明白,表锁是mysql中开销最小的锁,也是最容易发生锁冲突的锁;行锁是mysql中开销最大的锁,也是可以最大程度支持并发处理的锁。
由上表可知,意向锁会阻塞表级的S锁和X锁,但意向锁是不会阻塞任何行级锁和其它意向锁的。若没有意向锁的存在,则一个session想要获取某表的表级锁,那么它就要对该表逐行去检查是否有与其冲突的行级锁存在。若有了意向锁,则只需要检查与其冲突的意向锁是否存在,不用再逐行扫描了。举个例子:
session A在表t对某些行加了S锁,而且加行级S锁前必须先对表t加IS锁。这时;session B想对表t施加表级X锁,但它检测到了在表t上有IS锁,表级X锁和IS锁是冲突的,所以session B此时被阻塞。

innoDB加锁的方法:

1、意向锁是存储引擎自动加的,无需我们干预。
2、对于UPDATE, DELETE, INSERT语句,innoDB会自动给相应的数据集加X锁:
Session 1先更新:
Session 1先更新
Session 2试图对被修改的行加S锁,但被阻塞了:
在这里插入图片描述

3、用select… for share和select…for update分别加S锁和X锁

  • select…for update加S锁:
    Session 1用select… for share对某行加S锁:
    在这里插入图片描述
    Session 2试图对该行加X锁,但由于该行已被S锁锁住,故被阻塞:
    在这里插入图片描述
    Session 3对该行加S锁,S锁之间不会冲突:
    在这里插入图片描述

  • select…for update加X锁
    Session 1对某行加X锁:
    在这里插入图片描述
    Session 2试图对该行加X锁,但被阻塞:
    在这里插入图片描述

4、普通SELECT语句不加任何锁;
Session 1对某行加X锁:
在这里插入图片描述

Session 2直接select该行,由于未加锁,所以查得出来:
在这里插入图片描述

要注意的一点是:

innoDB的行锁是锁在索引的索引项上的,所以要用行锁,则必须用到索引来检索数据;如果用的是全表扫描,则innoDB加的是表锁。下面举例验证:

加锁时,若用索引检索,则加的是行锁:
websites表的索引如下,id列是该表的主键,故有主键索引:
在这里插入图片描述
Session 1用id检索某行,并对其加S锁:
在这里插入图片描述

Session 2用id检索其它行,并对其加X锁:
在这里插入图片描述
结论: 可以看到,两个Session在检索时都用到了索引,故加的是行锁,故检索不同行时两个Session不会产生锁冲突;

加锁时,若不用索引检索,则加的是表锁:
Session 1用name检索某行,并对其加S锁:
在这里插入图片描述

Session 2用索引列id检索其他行,并试图对其加X锁,但被阻塞:
在这里插入图片描述

结论: 可以看到,虽然两个Session检索的是不同行,但是由于Session1未使用索引检索,故对整张websites表加了S锁,导致Session 2无法对该表加行锁。

举报

相关推荐

0 条评论