【译文】MySQL InnoDB 使用的锁分析

InnoDB 使用的 锁类型html

  共享锁和排它锁mysql

  意向锁算法

  记录锁sql

  间隙锁数据库

  Next-key 锁并发

  插入意向锁高并发

  AUTO-INC 锁性能

 

共享锁和排他锁spa

  InnoDB实现了俩个标准的行级锁,共享锁和排它锁。code

    共享锁容许持有者读取一行

    排它锁容许持有者更新或者删除一行

  若是一个事物T1在 r 行持有一把共享锁,则来自于不一样的事物T2在 r 行上的锁请求将按照以下方法处理:

    T2请求共享锁能够当即被受权,所以T1和T2都持有了在 r 行上的共享锁

    T2请求排它锁不能够当即被受权。

  若是一个事物T1在 r 行持有一把排它锁,则来自与不一样事物T2在r上的任何锁请求将不会当即被受权。

 

意向锁

  InnoDB支持多粒度锁:指容许表级锁和行级锁共存。为了实如今多粒度级别上锁,额外的锁类型(意向锁)被使用。意向锁是一个表级锁,它代表将来在那张表上会有哪种锁类型(排他或者共享)被事物请求。

  InnoDB有俩种类型的意向锁(假设事物未来会在某张表t上请求锁):意向共享锁,意向排他锁。

  意向共享锁:指事物意图在表t上的某些行上加S锁

  意向排它锁:指事物意图在表t上的某些行上加X锁

  意向锁协议描述以下:

    事物在表t上的一行上加S锁以前,他必须获取IS锁或者在t上更强的锁(指表级锁)

    事物在表t上的一行上加X锁以前,他必须获取IX锁

  上述锁规则协议能够方便的归纳以下的兼容性矩阵:

  X IX S IS
X Conflict Conflict Conflict Conflict
IX Conflict Compatible Conflict Compatible
S Conflict Conflict Compatible Compatible
IS Conflict Compatible Compatible Compatible

    注:意向锁是MySQL本身自动处理,为了解决表级锁和行级锁的冲突,即提前检测锁冲突。

S、X、IS、IX锁兼容性矩阵为何是这样子呢?

一、意向锁之间彼此不会冲突,由于它们都只是“有意”,而不是真干,因此是能够兼容的。在加行锁以前,会使用意向锁判断是否冲突;
二、IX和X的关系等同于X和X之间的关系,为何呢?由于事务得到了IX锁,接下来就有权利获取X锁,这样就会出现两个事务都获取X锁的状况,这和咱们已知的X锁和X锁之间互斥是矛盾的;
三、S和IS、X和IS、IX和IS也能够由此推导出来。

  一个锁被授予一个事物,是在该锁与事物已获取的锁兼容的时候,而不是与现有锁冲突的时候。事物等待直到冲突的锁被释放。若是一个锁请求与现有的锁冲突,而且由于死锁不能被授予,一个错误会发生,MySQL本身决定哪一个事物回滚

 

  所以意向锁不阻塞任何事物,除了全表锁请求。IX锁和IS锁是用来代表某我的或者事物正在持有锁或者将要持有锁。

 

记录锁

  一个记录锁是在索引记录上的锁,仅锁住一行。例如:SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; 阻止任何其余事物插入、更新、删除c1=10的行,前提是c1有索引。

  记录锁锁住的只是记录的索引“记录”,及时一个表没有定义任何索引,InnoDB也会默认建立一个聚簇索引,并用来加锁。

  不符合where条件的记录锁会被释放。

 

间隙锁

  间隙锁是指锁住索引记录之间的空隙(并不锁住索引记录,即开区间),或者明确指定索引记录的第一个和最后一个,例如:SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE; 阻止任何其余事物的插入、更新和删除

  Gap能够仅有一个值,多个值或者为空。

  Gap锁是在性能和并发度上权衡的结果,并被某些事物隔离级别使用。

  Gap锁在一些使用惟一索引的来检索惟一行的语句中是没有必要的,由于索引的结果是惟一的,没有间隙,不会妨碍其余会话(事物)插入记录。注,那些语句中包含惟一索引和二级索引的仍然适用Gap锁。

  值得注意的是,在不一样事物中,锁冲突能够发生在同一个间隙里,例如一个事物A持有一把共享GAP锁在Gap间隙中,同时事物B持有一把排他的Gap锁,俩个Gap属于同一个。

    注,举一个例子,假设数据库存在id为1,2,3,5,7;事物1:select * from student where id between 3 and 9 for update; 事物2:select * from student where id = 8; 俩个事物共享(7-9)这个间隙锁,但互不影响。

    冲突Gap被容许的缘由是若是一个记录从索引中被清除了,不一样事物在这个记录上的Gap锁必须合并。

    注:上述状况未实验成功,首先是不太明白其意思,其次是若是删除索引记录,意味着加X锁,然而这个锁的排他性已是冲突了,并不能验证成功。若是有人直销烦请告知,不胜感激!

  Gap锁在InnoDB中是纯抑制做用,意思是Gap锁仅阻止其余事物插入这个gap间隙,他们不阻止不一样的事物在相同的gap上获取gap锁。所以,GapX锁和GapS锁有相同的效果。

  Gap锁能够被禁用,经过设置RC隔离级别,或者启用 innodb_locks_unsafe_for_binlog系统变量(当前已标记为了弃用),此时,在检索和扫描的时候Gap锁被禁用,且仅被用做外键检查和重复值检测。

注:当用惟一索引时,三种方法可能产生间隙锁:

  1. 惟一检索值不存在,此时会在索引中寻找“最小区间”加间隙锁;
  2. between and 条件筛选肯定索引间隙加锁;
  3. 检索值和比较操做符,例如大于小于检索值(此时符合的记录也会加记录锁,不只仅是间隙锁)

  

 

Next-key Locks

  Next-key锁是记录锁和Gap锁的结合。

  InnoDB 执行行级锁,所以,当检索或扫描表索引时,他设置S或者X锁到遇到的索引记录上。所以,行级锁其实是记录锁,一个索引记录上的next-key锁,一样影响索引记录以前的gap。就是说next-key锁是一个记录锁,加上一个gap(记录以前)锁。

  假设索引里面有10,11,13,20。则可能的next-key锁是:

(negative infinity, 10]
(10, 11]
(11, 13]
(13, 20]
(20, positive infinity)

  默认地,InnoDB提供的事物隔离级别是RR,此时InnoDB使用的是next-key锁,在检索和扫描的时候。以阻止幻读。next-key在使用惟一索引时会降级为记录锁,提升并发度。

 

插入意向锁(一种特殊的gap锁):

  插入意向锁是当插入操做执行时,设置的一种特殊的gap类型锁。这个lock标志一种插入行为:若是每一个事物插入gap中的位置不同时在多事物插入相同的gap状况不须要互相等待。这主要是提升并发插入效率。

 

AUTO-INC锁

  该锁类型是一种特殊的表级锁,在事物插入自动增加字段时使用。若是一个事物插入列值(自动增加列)到表中,任何其余的事物必须等待,所以插入的字段才会是连续的值。

   innodb_autoinc_lock_mode配置选项,控制自动增加锁使用的算法,它容许你选择插入操做时,如何来权衡可预测的自动增加值和最大并发度

 

注:

  排它锁和共享锁是指锁的性质,意图锁是意图。

  记录锁和Gap锁是锁的范围,这就会出现是在必定的范围加特定性质的锁的问题。

相关文章
相关标签/搜索