作者: 意大利大炮 | 来源:发表于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