Mysql共享锁和排他锁的关系 2019

Posted by Bink的博客 on May 7, 2019

mysql共享锁和排他锁的关系

一、S锁和X锁:S锁和X锁都属于行数

image-20190507112453230

二、意向锁:表锁,相互兼容,表明“某个事务持有了锁、或准备去持有锁”

1、意向锁的存在是为了协调行锁和表锁的关系,支持多粒度(表锁与行锁)的锁并存。

2: 1)意向共享锁(IS锁):事务在请求S锁前,要先获得IS锁 2)意向排他锁(IX锁):事务在请求X锁前,要先获得IX锁

3、例子:事务A修改user表的记录r,会给记录r上一把行级的排他锁(X),同时会给user表上一把意向排他锁(IX),这时事务B要给user表上一个表级的排他锁就会被阻塞。意向锁通过这种方式实现了行锁和表锁共存且满足事务隔离性的要求。

q1:为什么意向锁是表级锁呢?

当我们需要加一个排他锁时,需要根据意向锁去判断表中有没有数据行被锁定(行锁);

(1)如果意向锁是行锁,则需要遍历每一行数据去确认;

(2)如果意向锁是表锁,则只需要判断一次即可知道有没数据行被锁定,提升性能。

q2:意向锁怎么支持表锁和行锁并存?

(1)首先明确并存的概念是指数据库同时支持表、行锁,而不是任何情况都支持一个表中同时有一个事务A持有行锁、又有一个事务B持有表锁,因为表一旦被上了一个表级的写锁,肯定不能再上一个行级的锁。 (2)如果事务A对某一行上锁,其他事务就不可能修改这一行。这与“事务B锁住整个表就能修改表中的任意一行”形成了冲突。所以,没有意向锁的时候,让行锁与表锁共存,就会带来很多问题。于是有了意向锁的出现,如q1的答案中,数据库不需要在检查每一行数据是否有锁,而是直接判断一次意向锁是否存在即可,能提升很多性能。

三、下图表示意向锁和共享锁、排他锁的兼容关系。

1.当事务A对某个数据范围(行或表)上了“某锁”后,另一个事务B是否能在这个数据范围上“某锁”。 2.意向锁相互兼容,因为IX、IS只是表明申请更低层次级别元素(比如 page、记录)的X、S操作。 3.表级S锁和X、IX锁不兼容:因为上了表级S锁后,不允许其他事务再加X锁。 4.表级X锁和 IS、IX、S、X不兼容:因为上了表级X锁后,会修改数据,所以即使是行级排他锁,因为表级锁定的行肯定包括行级锁定的行,所以表级X和IX、X都不兼容。

注意:上了行级X锁后,行级X锁不会因为有别的事务上了IX而堵塞,一个mysql是允许多个行级X锁同时存在的,只要他们不是针对相同的数据行。

image-20190507112515442

四、更颗粒度的锁

  • 当InnoDB在判断行锁是否冲突的时候,除了最基本的IS IX S X锁的冲突判断意外,还有一套更精确的判断逻辑。除了上面说到的锁类型,InnoDB还将锁细分为如下几种子类型:
  • record lock(RK)
  • 锁直接加在索引记录上面,锁住的是key
  • gap lock(GK)
  • 间隙锁,锁定一个范围,但不包括记录本身。GAP锁的目的,是为了防止同一事务的两次当前读,出现幻读的情况
  • next key lock(NK)
  • 行锁和间隙锁组合起来就叫Next-Key Lock
  • insert intention lock(IK)
  • 如果插入前,该间隙已经由gap锁,那么Insert会申请插入意向锁。因为了避免幻读,当其他事务持有该间隙的间隔锁,插入意向锁就会被阻塞(不用直接用gap锁,是因为gap锁不互斥)。
  • 下面画的就是“精确模式”锁兼容矩阵 image-20190507112515442