zoukankan      html  css  js  c++  java
  • 【译文】MySQL InnoDB 使用的锁分析

    InnoDB 使用的 锁类型

      共享锁和排它锁

      意向锁

      记录锁

      间隙锁

      Next-key 锁

      插入意向锁

      AUTO-INC 锁

    共享锁和排他锁

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

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

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

      如果一个事物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锁

      上述锁规则协议可以方便的概括如下的兼容性矩阵:

     XIXSIS
    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锁兼容性矩阵为什么是这样子呢?

    1、意向锁之间彼此不会冲突,因为它们都只是“有意”,而不是真干,所以是可以兼容的。在加行锁之前,会使用意向锁判断是否冲突;
    2、IX和X的关系等同于X和X之间的关系,为什么呢?因为事务获得了IX锁,接下来就有权利获取X锁,这样就会出现两个事务都获取X锁的情况,这和我们已知的X锁和X锁之间互斥是矛盾的;
    3、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锁是锁的范围,这就会出现是在一定的范围加特定性质的锁的问题。

  • 相关阅读:
    1012 The Best Rank (25 分)(排序)
    1011. World Cup Betting (20)(查找元素)
    1009 Product of Polynomials (25 分)(模拟)
    1008 Elevator (20 分)(数学问题)
    1006 Sign In and Sign Out (25 分)(查找元素)
    1005 Spell It Right (20 分)(字符串处理)
    Kafka Connect 出现ERROR Failed to flush WorkerSourceTask{id=local-file-source-0}, timed out while wait
    flume、kafka、avro组成的消息系统
    Java23种设计模式总结【转载】
    Java编程 思维导图
  • 原文地址:https://www.cnblogs.com/pengyusong/p/6180478.html
Copyright © 2011-2022 走看看