• Mysql系列二:Mysql里的锁



    一、Mysql中的锁

    1、加锁的目的

    加锁的目的是为了解决隔离性问题,让事物之间互不影响,每个事物在操作数据前都加一把锁,若后来的事物发现持有锁只能等待。

    锁定分类有一下几种:

    基于锁的属性分类: 共享锁、排他锁。

    基于锁的粒度分类: 表锁、行锁(记录锁、间隙锁、临键锁)。

    基于锁的状态分类: 意向共享锁、意向排它锁。

    2、属性锁

    2.1、共享锁(Share Lock)

    共享锁又称为S锁,当一个事物A对数据加了共享锁之后,后续的事物只能读取数据,而不能做任何修改操作,也就是不能加写锁了,只有事物A的释放后,其他事物才能添加写锁。

    实现方式: select …lock in share mode

    2.2、排他锁(eXclusive Lock)

    排他锁又称为写锁,简称为X锁,当一个事物A对数据加了排他锁之后,后续的事物只能等待,无法读取也无法修改,等待事物A释放之后才能做后续的操作。

    实现方式: select …for update

    3、状态锁

    意向锁是 表锁 ,为了协调行锁和表锁的关系,支持多粒度(表锁与行锁)的锁并存。当一个事物试图对整个表进行加锁之前首先需要获取对应类的意向锁。

    意向共享锁: 当一个事务试图对整个表进行加共享锁之前,首先需要获得这个表的意向共享锁。

    意向排他锁: 当一个事务试图对整个表进行加排它锁之前,首先需要获得这个表的意向排它锁。

    意向锁作用:

    1、事物A执行了:update xxxx set name = ‘张三’ where id = 6 ,此时事物A就会对id为6的这条数据进行加排他锁。

    2、事物B此时执行了:update xxxx set name = ‘李四’ ,此时事物B对整个表进行操作,所以想要获得表级别排他锁,首先检查这个表有没有被其他的事物锁住,若没有再去检查每一行的数据是否被锁住,然后自己在加锁成功或失败。

    所以,事物B需要验证遍历表的所有数据才能判断出是否加锁,然后才能继续操作,浪费了大量的性能,所以出现了意向锁

    如果事物A加锁成功之后就设置一个标志,后续来的事物观察这个标志判断是否可以对整个表进行加锁,以此就不需要遍历每条数据了,提高性能。

    4、粒度锁(行锁、表锁)

    4.1、表锁

    表锁顾名思义指锁住的是整个表。特点是粒度较大,锁住整个表,易冲突但好维护。

    4.2、行锁

    行锁是对行级别所得一个统称,比如 记录锁(Record Lock)、间隙锁(Gap Lock)、临键锁(Next-Key Lock ),指锁住一行或者多行数据,若多个事务访问同一张表,只有被锁住的数据不能访问,其他数据可以访问。

    注意: 行锁都是需要命中索引才会生效的,若表没有索引则都是表锁。

    4.3、记录锁(Record Lock)

    ​ 记录锁是属于行锁的一种,记录锁的范围是表中的一条数据。

    select * from test where id = 10 for update;
    
    • 1

    这条SQL就会命中id为10的这条数据。

    触发条件: 精准命中条件,并且命中索引。

    4.4、间隙锁(Gap Lock)

    间隙锁是锁住表中的某个索引区间,是一个范围锁。使用间隙锁锁住的是一个区间,不包括具体数据,锁住的是空闲的空间。

    数据如下所示:

    s

    这儿会形成(- ∞ ,1),(1,10),(10,20),(20,30),(30,+ ∞ )这几个区间,间隙锁是开区间

    SELECT * FROM aa_test WHERE order_no BETWEEN 10 AND 20 FOR UPDATE;
    
    • 1

    间隙锁会找寻范围值最小值的前一个区间段以及返回值最大值的后区间段作为锁定区间,比如这儿间隙锁锁定的就是(1,10),(10,20),(20,30)这个区间段。
    若此时另一个事物执行如下sql:发现被阻塞了。

    INSERT INTO `aa_test`( `order_no`) VALUES (4);
    
    • 1

    4.5、临键锁(Next-Key Lock)

    是行锁的一种,innodb的默认行锁算法,总结来说就是记录锁以及间隙锁的结合,会把真实的记录锁住,也会锁住区间内的空闲空间。

    还用上面的数据进行讲解,会形成(- ∞ ,1],(1,10],(10,20],(20,30],(30,+∞),这些区间包含具体的数据。

    SELECT * FROM aa_test WHERE order_no BETWEEN 1 AND 13 FOR UPDATE;
    
    • 1

    这条SQL会锁住(- ∞ ,1],(1,10],(10,20] 区间的数据。

    5、查看锁状态

    1、查看是否锁表

    show status like%lock%
    • 1

    2、查询进程

    show processlist;
    
    • 1

    3、查询行锁、表锁状态

    ## 查看行锁的状态
    show status like 'innodb_row_lock_%';
    ##查看表锁的状态
    show status like 'table%';
    
    • 1
    • 2
    • 3
    • 4

    4、INFORMATION_SCHEMA库

    ## 内核中的当前活跃(ACTIVE)事务
    SELECT * FROM INFORMATION_SCHEMA.INNODB_TRX;
    ## 查看正在锁的事物,被阻塞的
    SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCKS;
    ## 查看等待锁的事物,被阻塞的
    SELECT * FROM INFORMATION_SCHEMA.INNODB_LOCK_WAITS;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
  • 相关阅读:
    【操作系统】进程:哲学家进餐问题
    面向AI时代的软件开发新范式
    运动品牌如何做到“全都要”?来看看安踏的答案
    java-php-python-ssm抑抑心理交流平台计算机毕业设计
    渗透测试-子域名发现
    基于攻防博弈的网络防御决策方法研究综述
    【408数据结构与算法】—单链表(五)
    Kinetics400/600/700数据集免费下载
    vue3 编写.netcore可视组件
    数学建模中所需要使用到的Matlab(从零开始介绍)
  • 原文地址:https://blog.csdn.net/zhengguofeng0328/article/details/127775953