您的当前位置:首页 >系统运维 >理清MySQL的行锁、意向锁、记录锁、间隙锁和临键锁 正文

理清MySQL的行锁、意向锁、记录锁、间隙锁和临键锁

时间:2025-11-04 08:12:06 来源:网络整理编辑:系统运维

核心提示

在日常开发工作中,Mysql是常用的数据库之一,突然某天Mysql数据库告警提示出现了死锁问题,为了解决死锁问题,我们就需要掌握一些关于Mysql的锁的知识。1、行锁 在InnoDB存储引擎中行级锁

在日常开发工作中,理清录锁临键Mysql是行锁常用的数据库之一,突然某天Mysql数据库告警提示出现了死锁问题,锁记锁和锁为了解决死锁问题,间隙我们就需要掌握一些关于Mysql的理清录锁临键锁的知识。

1、行锁行锁

    在InnoDB存储引擎中行级锁每次操作锁住对应的锁记锁和锁行数据,锁定粒度最小,间隙发生锁冲突的理清录锁临键概率最低,并发度最高。行锁InnoDB的锁记锁和锁数据是基于索引组织的,行锁是间隙通过对索引上的索引项加锁来实现的,而不是理清录锁临键对记录加的锁。在InnoDB存储引擎下实现了共享锁和排他锁这两种行锁,行锁以下是锁记锁和锁两种锁的介绍:

(1)共享锁(简称:S)

    允许一个事务去读一行,阻止其他事务获得相同数据集的排它锁。(加了共享锁之后可以读取,源码库但是不可以写) ,典型是在查询后面添加for share。在Mysql的performance_schema下的data_locks表中记录关于锁的相关信息,记录锁信息的表位置所示的:

图片

执行如下的sql语句:

复制BEGIN; #共享锁 SELECT * from stock where id = 8 FOR SHARE;1.2.3.4.5.

查询data_locks表的锁信息:

图片

S,REC_NOT_GAP:表示对id=8的数据添加一把读锁(S),其中REC_NOT_GAP表示锁的一个范围(是指到底去锁哪些数据),这里表示只锁住id=8的数据。

(2)排他锁(简称:X)

    允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁。(加了写锁之后其他的事务不可以添加任何的锁【读锁、写锁都不可以】)默认每次insert、update、delete的时候都是加排他锁,如下的更新sql:

复制BEGIN; #排他锁 update stock set num= 81 where id = 8;1.2.3.

查询data_locks表的b2b供应网锁信息:

图片

X,REC_NOT_GAP:表示对id=8的数据添加一把排他锁(X),同样的REC_NOT_GAP表示锁的一个范围。

    如果对select查询添加for update的时候,此时就是排他锁,如下的sql:

复制BEGIN; #排他锁 SELECT * from stock where id = 8 FOR UPDATE;1.2.3.

查询data_locks表的锁信息:

图片

排他锁和共享锁的兼容性如下锁整理:

图片

    在案例中我们使用的是主键id做为where的查询条件,假设我们现在不使用id而是使用一个非索引字段作作为查询的条件,sql如下所示:

复制BEGIN; #共享锁 SELECT * from stock where name = A FOR SHARE;1.2.3.

数据表中的现存的记录如下所示:

图片

执行sql后查询data_locks表的锁信息:

图片

我们可以发现目前锁类型就是表锁了。

2、记录锁

    锁一条真实存在的记录(数据库中真实存在的数据),如下图是数据表中的数据记录:

图片

通过sql查询id=8的记录,sql如下所示:

复制BEGIN; #共享锁 SELECT * from stock where id = 8 FOR SHARE;1.2.3.

锁的b2b信息网结果:

图片

3、间隙锁

    间隙是指索引跟索引之间的间隙,假设现在查询id=5的数据(数据库中id为5的数据不存在),如下的数据表数据:

图片

执行如下的sql:

复制BEGIN; #共享锁 SELECT * from stock where id = 5 FOR SHARE;1.2.3.

查询data_locks表的锁信息:

图片

    S表示的读锁,GAP表示的间隙的意思,8代表的是一个节点(真实的记录),这里的含义是1-8之间的间隙是锁住的,这个间隙之内不可以添加数据,但是可以修改数据。

4、临键锁

    临键锁是记录锁+间隙锁,因为在去加锁来锁数据的时候,那么可能既包含了区间也包含了一条真实的数据,假设数据表中的数据如下所示:

图片

现在执行sql:

复制BEGIN; #共享锁 SELECT * from stock where id > 5 and id < 14 FOR SHARE;1.2.3.

查询data_locks表的锁信息:

图片

    id=8这条数据的LOCK_MODE=S,它没有任何的标记,那么id=8这条数据就是临键锁(临键锁只标记了是X还是S);它表示既锁死了id=8这条数据,也锁死了id在1-8这个区间。

    id=14这条数据中,它没有锁死id=14这个数据,只锁死了一个gap的区间。

5、意向锁

    意向锁是为了提高粗粒度锁的性能而设置的一种预判机制(意向锁是为了协调行锁和表锁的关系,用于优化InnoDB加锁的策略),意向锁的主要作用是避免为了判断表是否存在行锁而去全表扫描(即在一个操作发起实际资源的锁申请行为之前,先对更粗力度的资源发起一个加锁意向声明),意向锁是由InnoDB在操作数据之前自动加的,不需要用户干预。如下所示的意向锁:

图片

    意向锁分为意向共享锁(IS锁)【事务在请求S锁前,要先获得IS锁】;意向排他锁(IX锁)【事务在请求X锁前,要先获得IX锁】

意向锁(IS/IX)和X锁是冲突的,如下所示事务A执行语句:

复制BEGIN; #共享锁 SELECT * from stock where id = 8 FOR SHARE;1.2.3.

事务B的执行语句:

复制BEGIN; #排他锁 update stock set num= 140 where id = 14;1.2.3.

执行的效果图如下所示:

图片

①事务A首先申请整个表的IS锁(成功)。

图片

②事务A申请id=8这一行的S锁(成功)。

图片

③事务B申请整个表的IX锁(成功);因为IS和IX锁是兼容的,并且IX锁和行级别的S锁也是兼容的。

图片

④事务B申请整个表的X锁(成功);

图片

所以整个过程的数据库锁的信息:

图片

    如果现在事务A给行记录id=8加共享锁成功后,事务B给id=8的行记录加排他锁,此时事务B就需要等待事务A释放锁才能加锁成功,如下图所示:

图片

数据库的锁信息如下所示:

图片

可以发现事务B此时在等待锁。

意向锁与其他锁的兼容性如下表整理:

图片

    意向锁是一种高效的锁机制,特别适用于支持行级锁的数据库系统,能够在多事务并发访问的环境下有效地管理锁,提高系统的并发性和数据一致性。