• 可重复读隔离级别下才会生效

    作用

    解决幻读

  • 幻读产生的原因是,行锁只能锁住行,但是新插入记录的动作,要更新的是记录之间的间隙

  • 在可重复读隔离级别下,普通的读是“快照读”,是不会读到别的事物提交的记录的;
  • 幻读仅指新插入的行
  • 幻读只产生在可重复读隔离级别以下的,或者当前读(select … for update/lock in share model)

    间隙锁的冲突

  • 间隙锁之间存在冲突关系,是往这个间隙之间插入记录。即保护这个间隙,不允许插入新值

  • 而如果两个事务都要去想一个间隙加间隙锁,则他们之间不会冲突

    Next-key lock

  • 间隙锁和行锁,合成next-key lock

  • 每个next-key lock是前开后闭区间

    示例

  • 如下SQL ``` create table t( id int(11) not null, c int(11) not null, d int(11) not null, primary key(id), key c_key(c) )engine=InnoDB;

insert into t values(0,0,0),(5,5,5),(10,10,10),(15,15,15),(20,20,20),(25,25,25); ```

  • 执行SQL:select * from t from update

    • 会形成7个next-key lock:(-∞,0]、(0,5]、(5,10]、(10,15]、(15,20]、(20,25]、(25,+supremum]
    • supermum:由于正无穷是开区间,所以为了满足前开后闭,这里InnoDB会加上一个不存在的最大值supermum

      间隙锁造成的死锁现象

      间隙锁 - 图1
  • 由于id=9这一行不存在,因此在session A 在t1时刻、session B在t2时刻,都会加上间隙锁(5,10)

  • 由于间隙锁之间不会重复,所以session B在t2时刻不会阻塞
  • session B在t3时刻向间隙锁的间隙之间插入一行记录,会被session A的间隙锁阻塞住
  • session A在t4时刻向间隙锁的间隙之间插入一行记录,会被session B的间隙锁阻塞住

    间隙锁其他影响

  • 由于使锁的范围更大,会导致并发度下降