MySQL——InnoDB存储引擎的锁

  锁是数据库系统系统区别于文件系统的一个关键特性。
参考:https://blog.ouyangsihai.cn/mysql-de-you-yi-shen-qi-suo.html

一、lock和 latch

1. latch

  latch在MySQL中是用来保证并发多线程操作操作临界资源的锁,锁定的对象线程,是和咱们使用的Java等传统语言中的锁意义相近,而且没有死锁检测的机制

2. lock

   lock是MySQL中在事务中使用的锁,锁定的对象是事务,来锁定数据库中表、页、行;通常只有在事务commit或者rollback后进行释放。lock是有死锁机制的,当出现死锁时,lock有死锁机制来解决死锁问题:超时时间(参数innodb_lock_wait_timeout)、wait-for graph。

我们通常讲的MySQL的“锁”,一般就是说的lock。以下就是InnoDB中“锁”的大分类:
在这里插入图片描述

二、lock的种类

MySQL Lock大体上可以分为:表锁、行锁、意向锁三种。
在这里插入图片描述
1.共享/排他锁


行锁分为:S Lock和X Lock。S Lock :读锁;X Lock:写锁
两锁之间的兼容性如下。

       X         S
X     不兼容     不兼容
S     不兼容     兼容

简单总结为:读锁可以读、不可写;写锁不可读、也不可写。

2.意向锁


可以参考:https://juejin.im/post/5b85124f5188253010326360
意向锁是一种不与行级锁冲突表级锁,这一点非常重要。意向锁分为两种:

  • 意向共享锁(intention shared lock, IS):事务有意向对表中的某些行加共享锁(S锁)
  • 事务要获取某些行的 S 锁,必须先获得表的 IS 锁。
    SELECT column FROM table ... LOCK IN SHARE MODE;
    
  • 意向排他锁(intention exclusive lock, IX):事务有意向对表中的某些行加排他锁(X锁)
  • 事务要获取某些行的 X 锁,必须先获得表的 IX 锁。
    SELECT column FROM table ... FOR UPDATE;
    

    即:意向锁是有数据引擎自己维护的,用户无法手动操作意向锁,在为数据行加共享 / 排他锁之前,InooDB 会先获取该数据行所在在数据表的对应意向锁

    InnoDB支持多粒度的锁,即:允许表锁和行锁同时存在。
    但是,假如表锁覆盖了行锁的数据,所以表锁和行锁也会产生冲突。如:

    trx1 BEGI
    trx1 给 T1 加X锁修改数据。
    
    trx2 BEGIN
    trx2 给 T1 加表锁修改表结构
    

    表锁和行锁之间就产生了冲突,为了解决这种表锁和行锁共存的问题,就产生了意向锁这个东西。
    意向锁:从字面意思也很好理解,就是提前表明一个“意向”

    意向锁仅仅是表明意向,它其实非常弱,意向锁之间可以相互并行,并不是排斥的。意向锁之间的兼容性问题:

          IS     IX
    IS   兼容    兼容
    IX   兼容    兼容
    

    于是,上述现象就变为了:

    trx1 BEGIN
    trx1 给 T1 先加IX ,然后在某一行记录加X锁。
    
    trx2 BEGIN
    trx2 给 T1 加表锁X(事务被阻塞,等待加锁成功)
    
    trx2 修改表结构
    

    意向锁存在的意义是什么呢?

    ”没有意向锁,行锁和表锁照样可以共存,试问如何共存?” “查看表中某一行存在X锁” “如何查看呢?” 唯有全表扫描…

      意向锁的存在就是解决了“全表扫描”的性能问题,所以,意向锁一定是“表级”锁,告诉整张表XXX行存在X锁。此时假如进行表操作就会被阻塞。

  • 总结
  • InnoDB 支持多粒度锁,特定场景下,行级锁可以与表级锁共存。
    意向锁之间互不排斥,但除了 IS 与 S 兼容外,意向锁会与 共享锁 /排他锁 互斥。
    IX,IS是表级锁,不会和行级的X,S锁发生冲突只会和表级的X,S发生冲突
    意向锁在保证并发性的前提下,实现了行锁和表锁共存且满足事务隔离性的要求。

    3.主键自增锁
      自增锁(auto-inc Locks)是一种特殊的表级锁,专门针对事务插入AUTO_INCREMENT类型的列,往往就是主键列。可以保证主键的值自增是“原子操作”,不会出现一致性、唯一性问题。

    4.行锁的具体分类
    在这里插入图片描述
    InnoDB存储引擎有以上3种行锁算法。以上3种,都是实现在索引上的。

    ①记录锁(Record Lock)
    记录锁(Record Lock)总是会去锁住索引记录。
    假如没有任何一个索引,那么InnoDB会锁住隐形创建的那个主键。

    注意:这里锁的是索引,不一定只是主键索引哦,还可能是二级普通索引。

    ②间隙锁(Gap Lock)
    顾名思义,它会封锁索引记录中的“缝隙”,防止其他事务在“缝隙”中插入数据。
    它锁定的是一个不包含索引本身的范围。

    例如以下索引数据:
    在这里插入图片描述
    间隙锁(Gap Lock)可以锁的将是以下范围
    在这里插入图片描述

    具体的范围还要根据查询条件不同而定。
    间隙锁开启的事务隔离级别是 Repeatable Read,如果把数据库事务级别降为Read Committed(默认是 Repeatable Read),间隙锁则会自动失效。

    ③ 临键锁(Next-Key Lock)
    Next-Key Lock可以说是记录锁(Record Lock)和间隙锁(Gap Lock)的组合,既封锁了”缝隙”,又封锁了索引本身

    还是上面的索引数据:
    在这里插入图片描述
    临键锁(Next-Key Lock)锁住的范围将是:
    在这里插入图片描述

    Next-key Lock在索引具有唯一性的时候,例如主键索引的数据,将会降级为记录锁(Read Lock),以增加并发性。
    例如:

            T1                                     T2
            BEGIN;                   |            
       select * From T               |           
       where id = 5 for update       |
    ---------------------------------------------------------------
                                     |            BEGIN; 
                                     |          Insert into t (4, xx);
    ---------------------------------------------------------------              
                                     |          COMMIT
                                     |             
    ----------------------------------------------------------------
         COMMIT                      |                            
                                     |
                                     |
    -----------------------------------------------------------------
    

    以上情况,就会把Next-key Lock降级为记录锁(Read Lock)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值