• SHARED LOCK / EXCLUSIVE LOCK  (row-level)

    共享锁允许事务持有读一行的锁;

    排他锁允许事务持有更新或删除一行的锁。

    如果事务T1持有行r上的共享锁S,那么其他的事务T2获得行r上的锁有如下情况:
      T2可以立即获得共享锁S。
      T2不能立即获得排他锁X。

    如果事务T1持有行r上的排他锁X,T2想在行r上获得任何类型的锁都不会立即得到,必须等待T1释放了行r上的排他锁。




  • INTENTION LOCK  (table-level)

    为什么需要意向锁。


    InnoDB实现多粒度锁机制,允许表锁和行锁的共存。

    意向锁是表级锁,它表明这个事务在接下来将对表中的一行请求什么类型的锁(S/X)。

    • intention shared lock , 表明事务T将要在表t的个别行上加S锁(将要读取某些行);  
      例如 select ... lock in share mode 
    • intention exclusive lock , 表明事务T将要在表t的个别行上加X锁(将要  U/D 某些行)。
      例如 select ... for update  

    意向锁的协议如下:

    • 事务在获得表中一行的S锁之前,它必须首先获得这张表上的IS锁,或更stronger的锁
    • 事务在获得表中一行的X锁之前,它必须首先获得这张表上的IX锁,或更stronger的锁

    锁类型的兼容矩阵列表如下


    XIXSIS
    X××××
    IX××

    S××
    IS×


    当一个事务请求某个类型的锁时,如果这个类型的锁与请求对象上持有的锁相兼容,那么会成功获得请求的锁。

    如果请求的锁与当前请求对象上持有的锁相冲突,那么事务就会等待已存在的锁释放。如果等待的这个锁不可能被授予,就会发生死锁。


    意向锁的主要作用是表明某个事务正在锁住某一行、或将要锁住某一行。

      




  • RECORD LOCK

    Record lock是在索引记录上的锁。


    Record locks总是锁住索引记录,即便一个表没有定义索引。这种情况下InnoDB创建隐藏的集簇索引,用这个隐藏的集簇索引来进行record locking。






  • GAP LOCK

    间隙锁是锁在index records之间间隙上的锁,或者第一个index record之前的间隙、最后一个index record之后的间隙。

    例如: SELECT c1 FROM t where c1 BETWEEN 10 and 20  FOR UPDATE ; 这句SQL会阻止其他事务插入c1为15的记录, 

    【根据index record的记录来确定间隙锁的范围

    如果10 和 20 都有具体的index record , 那么锁住的范围是10-20 ; 

    如果10 和 20 没有具体的index record , 那么锁住的范围是  10之前的index record  - 20 之后的index record 。

    不管是否有这条记录都会阻止插入,因为这个间隙都被锁住了。

    一个间隙可能跨越一个单一的索引值、多个索引值、甚至是空。

    间隙锁需要综合考虑性能和并发,只在某些事务隔离级别中才会使用。


    对于使用唯一索引查找唯一行、然后进行锁定的语句来说,不需要间隙锁。

    (如果查询条件只包含唯一索引的部分列,这种情况仍需要间隙锁)。



    需要注意的是,不同的事务可以在一个gap上持有冲突的锁。例如,当事务B持有排他gap lock(gap X-lock)锁,事务A可以同时持有共享gap lock(gap S-lock) 锁。这种情况的原因是因为,如果一条记录从index中被purge时,在这条记录上,当前事务gap锁和其他事务上的gap锁必须被merged。
    Gap lock是抑制性的,这表示gap lock只会阻止其他事务插入新的记录到这个gap中。不会阻止其他的事务在相同gap上获取gap locks。因此,gap x-lock 和 gap s-lock的影响是相同的。
    gap lock 可以被显式的禁止。在事务级别更改为read commited , 或innodb_locks_unsafe_for_binlog变量(已废弃)被启用的情况下。在这种情况,gap locking在查询、索引扫描时会被禁用,只会用来做外键约束检查和重复键检查。




  • NEXT-KEY LOCK 


    next-key lock是一个record lock和这个record lock之前的gap lock的组合。


    InnoDB在查找或浏览表索引的时候,InnoDB会在遇到的每个index record上加S或X锁。

    row-level锁实际上是index-record锁。

    index record上的next-key锁同时会影响这个index record之前的gap。

    如果一个session在记录R上持有S或X锁,另外的session不能立即往R之前的gap中插入新的record。   

    怎么实验,测试结果不符。正确的理解应该为:这个锁是在查找或浏览索引时持有的,一旦找到响应的记录,该锁释放?

    当实验语句使用范围条件时,出现next-key现象。会锁住范围区间前后两个index record之间的所有记录。


    假设一个索引包含记录如下: 10,11,13和20。可能有的next-key locks情况如下:
    ( -∞ , 10]
    (10 , 11]
    (11 , 13]
    (13 , 20]
    (20 , +∞)
    PS:(13 , 20] 意为 13 < x <= 20。


    默认情况下,InnoDB操作是在repeatable read事务隔离级别。在这种隔离级别下,InnoDB使用next-key locks来防止产生幻读。






  • INSERT INTENTION LOCK 

    insert intention lock是一种间隙锁,在插入操作之间加锁。


    多个事务插入相同index gap时,如果不是插入相同位置的记录,彼此不会互相等待。

    例如有索引记录4和7,当不同的事务试图分别插入5和6,在获得插入行的X锁之前,会首先获得4和7之间的间隙上的插入意向锁。

    但他们不会互相阻塞,因为他们插入的不是相同的行。





  • AUTO-INC LOCK (table-level)

    Auto-inc锁是一种特殊的表级锁,事务插入具有自增列的表时需要获得此锁。

    简单的说,就是一个事务正在插入表,那么其他插入表的事务必须等待这个当前插入事务完成,以保证主键值的连续。


    配置参数innodb_autoinc_lock_mode控制auto-increment 锁所使用的算法。



  • predicate locks for spatial indexes

    空间索引。待续。


    InnoDB supports SPATIAL indexing of columns containing spatial columns (see Section 11.4.8, “Optimizing Spatial Analysis”).

    To handle locking for operations involving SPATIAL indexes, next-key locking does not work well to support REPEATABLE READ or SERIALIZABLE transaction isolation levels. There is no absolute ordering concept in multidimensional data, so it is not clear which is the “next” key.

    To enable support of isolation levels for tables with SPATIAL indexes, InnoDB uses predicate locks. A SPATIAL index contains minimum bounding rectangle (MBR) values, so InnoDB enforces consistent read on the index by setting a predicate lock on the MBR value used for a query. Other transactions cannot insert or modify a row that would match the query condition.

  • No labels