zoukankan      html  css  js  c++  java
  • innodb事务锁

    innodb事务锁

    根据文档innodb锁分为以下几种:

    • 意向锁:

      就是简单的IX,IS这类意向锁,这个容易理解,比如要在表上读取一行记录,那么表可能会被加IS锁,在表上写入就会被加IX锁

    • 行锁:
      这个也非常容易理解,就是在行上面加锁,S锁或者X锁

    • gap锁:
      gap锁就是为了在repeatable read隔离级别下消除幻读引入的一种锁,打到serializable隔离级别的效果

    • next-key锁:
      其实这个锁是有gap锁和record锁组成的,LOCK_ORDINARY 表示next-key lock 但是在8.0中已经看不出来了。

    • 插入意向锁(INSERT_INTENTION)
      插入意向锁是gap锁的一种,2个插入意向所gap锁并不会产生冲突。

    repeatable read 隔离级别

    在这个隔离级别下,innodb为了实现repeatable read消除幻读,达到serializable的效果就引入了gap lock。

    next-key lock和gap lock

    LOCK_ORDINARY 表示next-key lock 但是在8.0中已经看不出来了,在performance_schema.data_locks中是gap锁和record2条记录:

     begin;
     update id = 45 where i=40;
    

    在另外一个会话中执行:

     select thread_id,engine_transaction_id,object_name,index_name,lock_type,lock_mode,lock_status,lock_data from data_locks;
    
    thread_id engine_transaction_id object_name index_name lock_type lock_mode lock_status lock_data
    240089 5446 l NULL TABLE IX GRANTED NULL
    240089 5446 l i RECORD X GRANTED 40, 50
    240089 5446 l PRIMARY RECORD X,REC_NOT_GAP GRANTED 50
    240089 5446 l i RECORD X,GAP GRANTED 60, 60
    240089 5446 l i RECORD X,GAP GRANTED 40, 45

    第2条和第5条组合其实就是一个next-key lock
    第3条锁定primary 50 是因为原来的id=50

    插入意向锁(INSERT_INTENTION lock)

    在repeatable read隔离级别下,insert会先去判断一下 insert intention lock若成功,插入然后释放。且2个插入意向锁在同一个gap中并不会堵塞测试也很简单在上面事务的基础上执行语句:

    insert into l values(60,35);
    

    查看锁信息:

    thread_id engine_transaction_id object_name index_name lock_type lock_mode lock_status lock_data
    240289 5447 l NULL TABLE IX GRANTED NULL
    240289 5447 l PRIMARY RECORD S,REC_NOT_GAP GRANTED 60
    240289 5447 l i RECORD X,GAP,INSERT_INTENTION WAITING 40, 45
    240089 5446 l NULL TABLE IX GRANTED NULL
    240089 5446 l i RECORD X GRANTED 40, 50
    240089 5446 l PRIMARY RECORD X,REC_NOT_GAP GRANTED 50
    240089 5446 l i RECORD X,GAP GRANTED 60, 60
    240089 5446 l i RECORD X,GAP GRANTED 40, 45

    而执行成功后锁会变成:

    thread_id engine_transaction_id object_name index_name lock_type lock_mode lock_status lock_data
    240289 5454 l NULL TABLE IX GRANTED NULL

    也就是说插入意向锁已经被释放。

    在2个会话中分别执行,发现并不会堵塞执行成功:

     begin;
      insert into l values(52,51);
    
     begin;
     insert into l values(51,50);
    

    锁信息:

    thread_id engine_transaction_id object_name index_name lock_type lock_mode lock_status lock_data
    240289 5454 l NULL TABLE IX GRANTED NULL
    240089 5453 l NULL TABLE IX GRANTED NULL

    read commit 隔离级别

    因为innodb的特点,mysql的update并不会堵塞select语句。除非显示的提示加共享锁。
    在read commit隔离级别下:

    begin;
    update l set id = 45 where i=40;
    
    thread_id engine_transaction_id object_name index_name lock_type lock_mode lock_status lock_data
    240089 5455 l NULL TABLE IX GRANTED NULL
    240089 5455 l i RECORD X,REC_NOT_GAP GRANTED 40, 50
    240089 5455 l PRIMARY RECORD X,REC_NOT_GAP GRANTED 50

    和之前的相比上了lock_mode 少了带gap的标记,原先的x锁中也加了rec_not_gap。也就是说read commit不再锁定数据的gap。

    堵塞判断

    innodb堵塞判断因为有了gap,next-key,insert intention锁变的复杂(lock_rec_has_to_wait函数中体现):

    1. 首选判断意向锁,为此还定义了一个堵塞矩阵:
    
     static const byte lock_compatibility_matrix[5][5] = { 
        /**         IS        IX         S          X           AI */ 
        /* IS */ { TRUE, TRUE, TRUE, FALSE, TRUE}, 
        /* IX */ { TRUE, TRUE, FALSE, FALSE, TRUE}, 
        /* S */ { TRUE, FALSE, TRUE, FALSE, FALSE}, 
        /* X */ { FALSE, FALSE, FALSE, FALSE, FALSE}, 
        /* AI */ { TRUE, TRUE, FALSE, FALSE, FALSE} };
    
    1. 即使步骤1冲突,根据不同的lock_mode 开始判断,以下情况不需要等待:

      • 如果请求锁住的是 supremum 或者 LOCK_GAP 为 1 并且 LOCK_INSERT_INTENTION 为 0
      • 如果请求锁 LOCK_INSERT_INTENTION 为 0 并且已有锁是 LOCK_GAP 为 1
      • 如果请求锁 LOCK_GAP 为 1,请求锁 LOCK_REC_NOT_GAP 为 1
      • 如果已有锁 LOCK_INSERT_INTENTION 为 1

    参考:

    MySQL · 引擎特性 · InnoDB 事务锁系统简介
    MySQL · 引擎特性 · Innodb 锁子系统浅析

  • 相关阅读:
    HashMap_经典存储_经典分拣思路
    (GOF23设计模式)_单例模式_应用场景_饿汉式_懒汉式
    sql简单测试
    Java概述
    搭建集群时的问题总结
    在Java连接hbase时出现的问题
    JavaAPI与hbase的交互
    Resourcemanager的高可用
    hbase安装
    hbase报错org.apache.hadoop.hbase.TableExistsException: hbase:namespace
  • 原文地址:https://www.cnblogs.com/Amaranthus/p/13496107.html
Copyright © 2011-2022 走看看