作者: 意大利大炮 | 来源:发表于2022-05-23 14:22 被阅读0次

    锁类型

    • 共享锁和排他锁
      行级锁
      lock mode S:共享锁(读锁)
      lock mode X:排他锁(写锁)

    • 意向锁
      InnoDB支持多粒度锁定,允许行锁和表锁共存。为了使多粒度级别的锁定变得实用,InnoDB请使用意图锁。意向锁是表级锁,它指示事务稍后对表中的行需要哪种类型的锁(共享或独占)。有两种类型的意图锁:
      lock mode IS:意向共享锁
      lock mode IX:意向排他锁
      意图锁定协议如下:
      在事务可以获取表中行的共享锁之前,它必须首先获取IS表上的锁或更强的锁。
      在事务可以获取表中行的排他锁之前,它必须首先获取IX 表上的锁。
      下面的矩阵总结了表级锁类型的兼容性。

    X IX S IS
    X 冲突 冲突 冲突 冲突
    IX 冲突 兼容的 冲突 兼容的
    S 冲突 冲突 兼容的 兼容的
    IS 冲突 兼容的 兼容的 兼容的

    排他锁种类

    • 记录锁(RECORD LOCKS)
      记录锁是对索引记录的锁。例如, SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; 阻止任何其他事务插入、更新或删除值为 的t.c110
      记录锁总是锁定索引记录,即使定义的表没有索引。对于这种情况, InnoDB创建一个隐藏的聚集索引并将该索引用于记录锁定。请参阅 第 15.6.2.1 节,“聚集索引和二级索引”
      记录锁的事务数据在InnoDB 监视器 输出 SHOW ENGINE INNODB STATUS中 显示类似于以下内容:
    RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t`
    trx id 10078 lock_mode X locks rec but not gap
    Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
     0: len 4; hex 8000000a; asc     ;;
     1: len 6; hex 00000000274f; asc     'O;;
     2: len 7; hex b60000019d0110; asc        ;
    
    image.png
    • 间隙锁(Gap Locks)

    • 下一键锁(Next-Key Locks)
      lock

    相互关系
    X锁:不能有S或X锁
    S锁:不能有X锁

    多线程批量新增死锁场景;

    共有10个线程,每个线程一次新增200条数据。

    • 场景1
      表中有一个主键和一些普通二级索引(非唯一索引).
      主键值为雪花算法生成,每次生成的值,一定是表里最大值。
      结论:不会死锁

    • 场景2
      表中有一个主键和一些普通二级索引(非唯一索引).
      主键值为其他方式生成,且每次生成的值,随机分布在表中id的任意区间。
      结论:主键死锁

    • 场景3
      表中有一个主键和一个唯一索引
      主键值为雪花算法生成,且每次生成的值,一定是表里最大值。
      唯一索引字段值为其他方式生成,且每次生成的值,随机分布在表中此字段的任意区间
      结论:唯一索引字段死锁

    • 原因;结论待验证
      某一Thread优先执行insert,由于存在唯一字段,需要校验唯一性,需要先加锁(防止值发生变更),加锁时,如果能找到该索引值,就加记录锁(只锁定此索引),若不能找到,则锁定最近的两个索引区间。
      场景2/3,每次insert会有200条数据,最多可能会锁住200个区间,多个事务就可能存在死锁冲突。
      场景1,每次insert第一次扫描的区间一定是:表中最大值的索引->无穷大。也就防止了其他事务加锁的可能性。

    锁调试

    • 查看锁等待情况
      select * from innodb_lock_waits;
    • 查看相关锁信息
      SELECT * FROM innodb_locks;

    insert加锁流程

    执行 insert 语句,对要操作的页加 RW-X-LATCH,然后判断是否有和插入意向锁冲突的锁,如果有,加插入意向锁,进入锁等待;如果没有,直接写数据,不加任何锁,结束后释放 RW-X-LATCH;并加X锁;

    死锁排查语句

    select * from innodb_lock_waits;
    SELECT * FROM innodb_locks;
    SELECT * FROM information_schema.INNODB_TRX;
    SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
    SHOW OPEN TABLES where In_use > 0;
    show engine innodb status;
    
    

    相关文章

      网友评论

          本文标题:

          本文链接:https://www.haomeiwen.com/subject/stdaurtx.html