Innodb事务隔离级别及锁机制(四)--gap锁

 gap锁或next-key锁的作用: 防止幻读。通过锁阻止特定条件的新记录的插入

什么时候会取得gap lock或nextkey lock: 和隔离级别有关,只在REPEATABLE READ或以上的隔离级别下的特定操作才会取得gap lock或nextkey lock。locking reads,UPDATE和DELETE时,除了对唯一索引的唯一搜索外都会获取gap锁或next-key锁

获取gap lock的两种情况:

1 事务隔离级别为REPEATABLE-READ,innodb_locks_unsafe_for_binlog参数为0,且sql走的索引为非唯一索引

2 事务隔离级别为REPEATABLE-READ,innodb_locks_unsafe_for_binlog参数为0,且sql是一个范围的当前读操作,这时即使不是非唯一索引也会加gap lock

Next-Key Locks

在默认情况下,mysql的事务隔离级别是可重复读,并且innodb_locks_unsafe_for_binlog参数为0,这时默认采用next-key locks。所谓Next-Key Locks,就是Record lock和gap lock的结合,即除了锁住记录本身,还要再锁住索引之间的间隙。

下面我们针对大部分的SQL类型分析是如何加锁的,假设事务隔离级别为可重复读

select .. from  

不加任何类型的锁

select...from lock in share mode

在扫描到的任何索引记录上加共享的(shared)next-key lock,还有主键聚集索引加排它锁 

select..from for update

在扫描到的任何索引记录上加排它的next-key lock,还有主键聚集索引加排它锁 

扫描二维码关注公众号,回复: 138545 查看本文章

update..where   delete from..where

在扫描到的任何索引记录上加next-key lock,还有主键聚集索引加排它锁 

insert into..

简单的insert会在insert的行对应的索引记录上加一个排它锁,这是一个record lock,并没有gap,所以并不会阻塞其他session在gap间隙里插入记录。不过在insert操作之前,还会加一种锁,官方文档称它为insertion intention gap lock,也就是意向的gap锁。这个意向gap锁的作用就是预示着当多事务并发插入相同的gap空隙时,只要插入的记录不是gap间隙中的相同位置,则无需等待其他session就可完成,这样就使得insert操作无须加真正的gap lock。想象一下,如果一个表有一个索引idx_test,表中有记录1和8,那么每个事务都可以在2和7之间插入任何记录,只会对当前插入的记录加record lock,并不会阻塞其他session插入与自己不同的记录,因为他们并没有任何冲突。

假设发生了一个唯一键冲突错误,那么将会在重复的索引记录上加读锁。当有多个session同时插入相同的行记录时,如果另外一个session已经获得改行的排它锁,那么将会导致死锁。


猜你喜欢

转载自blog.csdn.net/asdfsadfasdfsa/article/details/80046020