MySQL InnoDB加锁规则分析

这篇具有很好参考价值的文章主要介绍了MySQL InnoDB加锁规则分析。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.  基础知识回顾

MySQL InnoDB加锁规则分析

1、索引的有序性,索引本身就是有序的

2、InnoDB中间隙锁的唯一目的是防止其他事务插入间隙。间隙锁可以共存。一个事务取得的间隙锁并不会阻止另一个事务取得同一间隙上的间隙锁。共享和独占间隔锁之间没有区别。它们彼此之间不冲突,并且执行相同的功能。

3、MySQL默认隔离级别是 REPEATABLE-READ

4、加锁的对象是索引,加锁的基本单位是next-key锁,而行锁和间隙锁,是由next-key锁退化而来的

5、记录锁,锁的是索引,而非数据本身

6、间隙锁是开区间,next-key锁是前开后闭区间

7、意向锁是表级锁,它相当于一个标志,可以用来提高加锁的效率

8、间隙锁的目的是为了防止幻读,在“读已提交”隔离级别下允许幻读,所以如果隔离级别是“读已提交”,就不会用到间隙锁,更不会用到next-key锁。因此,只有“可重复读”及以上隔离级别下,才会有next-key锁

9、InnoDB中锁住的是索引。对辅助索引加锁时,辅助索引所对应的主键索引也会被锁住。

10、所谓“间隙”本质是又间隙右边的那条记录决定的

 

接下来,具体看一下走不同的索引时的加锁情况。本例中使用的MySQL版本为8.0.30

SELECT VERSION();
SHOW VARIABLES LIKE 'transaction_isolation';
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout';

MySQL InnoDB加锁规则分析

MySQL InnoDB加锁规则分析

测试表结构及数据如下:

MySQL InnoDB加锁规则分析

MySQL InnoDB加锁规则分析

2.  案例分析

LOCK_MODE不同值的含义:

  • X :代表next-key锁
  • X,GAP :代表间隙锁
  • X,REC_NOT_GAP :代表记录锁

2.1.  主键索引

情况一:等值查询,存在

Session A Session B
BEGIN;
SELECT * FROM t_user WHERE id = 10 FOR UPDATE;
 
 

INSERT INTO t_user (id, `name`, id_card_no, birthday, score) VALUES (9, '于禁', '1012', '2023-11-01', 1);

Affected rows: 1

MySQL InnoDB加锁规则分析

首先对表加意向排它锁,然后对主键加记录锁,可以看到只锁住了id=10这个主键索引

情况二:等值查询,不存在

Session A Session B Session C
BEGIN;
SELECT * FROM t_user WHERE id = 5 FOR UPDATE;
   
 

INSERT INTO t_user (id, `name`, id_card_no, birthday, score) VALUES (6, '于禁', '1012', '2023-11-01', 1);

1205 - Lock wait timeout exceeded; try restarting transaction

 
   

UPDATE t_user SET score = score + 1 WHERE id = 10;

Affected rows: 1

MySQL InnoDB加锁规则分析

加锁范围: (-∞, 10)

注意,是开区间,10并没有被锁

情况三:范围查找

Session A Session B Session C
BEGIN;
SELECT * FROM t_user WHERE id >= 10 AND id < 11 FOR UPDATE;
   
 

INSERT INTO t_user (id,`name`,id_card_no,birthday,score) VALUES (9,'典韦','1011','2022-12-19',1)

Affected rows: 1

 
   

INSERT INTO t_user (id,`name`,id_card_no,birthday,score) VALUES (18,'徐晃','1018','2022-12-09',1);

1205 - Lock wait timeout exceeded; try restarting transaction

MySQL InnoDB加锁规则分析

一个记录锁10,加一个间隙锁(10, 20),合起来就是[10, 20)

锁定区间:[10, 20)

Session A Session B Session C
BEGIN;
SELECT * FROM t_user WHERE id >= 10 AND id <= 20 FOR UPDATE;
   
 

UPDATE t_user SET score = score + 1 WHERE id = 20;

1205 - Lock wait timeout exceeded; try restarting transaction

 
   

INSERT INTO t_user (id,`name`,id_card_no,birthday,score) VALUES (21,'张辽','1021','2022-12-09',1);

Affected rows: 1

id=10上加了记录锁,id=20上加了next-key锁

next-key锁是前开后闭区间,所以,最终锁定区间为:[10,20]

如果这里不是id>=10,而是id>10的话,最终只会在id=20上加next-key锁,这种情况下锁定区间为:(10,20]

2.2.  唯一索引(非主键)

情况一:等值查询,存在

Session A Session B
BEGIN;
SELECT * FROM t_user WHERE id_card_no = '1003' FOR UPDATE;
 
 

UPDATE t_user SET score = score + 1 WHERE id = 30;

1205 - Lock wait timeout exceeded; try restarting transaction

MySQL InnoDB加锁规则分析

辅助索引 ('1003',30)加记录锁,同时,主键索引上id=30加记录锁

情况二:等值查询,不存在

先看一眼现在的数据

MySQL InnoDB加锁规则分析

Session A Session B Session C
BEGIN;
SELECT * FROM t_user WHERE id_card_no = '1042' FOR UPDATE;
   
 

INSERT INTO t_user (id,`name`,id_card_no,birthday,score) VALUES (52,'许褚','1041','2023-01-01',1);

1205 - Lock wait timeout exceeded; try restarting transaction

 
   

UPDATE t_user SET score = score + 1 WHERE id_card_no = '1041';

Affected rows: 0

MySQL InnoDB加锁规则分析

只在辅助索引idx_card上加了间隙锁,锁定范围是:('1040', '1050')

索引是有序的,尽管索引字段类型是字符串类型,仍然是有序的

因为是间隙锁,所以没有锁定1050,也就自然不会给id=50加记录锁

值得注意的是,在('1040', '1050')这个区间内插入是不行的,但是更新是可以的

情况三:范围查找

Session A Session B Session C
BEGIN;
SELECT * FROM t_user WHERE id_card_no <= '1024' FOR UPDATE;
   
 

INSERT INTO t_user (id,`name`,id_card_no,birthday,score) VALUES (11,'潘凤','1011','2023-01-01',1);

1205 - Lock wait timeout exceeded; try restarting transaction

 
   

INSERT INTO t_user (id,`name`,id_card_no,birthday,score) VALUES (11,'潘凤','1031','2023-01-01',1);

Affected rows: 1

MySQL InnoDB加锁规则分析

主键索引上id=10和id=20都加了记录锁

辅助索引idx_card上加了Next-key锁,锁定范围为:(-∞, '1010']、('1010', '1020']、('1020', '1030']

2.3.  非唯一索引(普通索引)

情况一:等值查询,存在

Session A Session B Session C
BEGIN;
SELECT * FROM t_user WHERE birthday = '2023-12-01' FOR UPDATE;
   
 

UPDATE t_user SET score = score + 1 WHERE birthday = '2023-12-11';

Affected rows: 0

 
   

UPDATE t_user SET score = score + 1 WHERE birthday = '2023-12-09';

Affected rows: 0

MySQL InnoDB加锁规则分析

主键索引id=10加记录锁

辅助索引idx_birthday上,'2023-12-01'上加Next-key锁,'2023-12-12'上加间隙锁

加锁区间:(-∞, 2023-12-01]、(2023-12-01, 2023-12-12)、id=10

因为是非唯一索引,所以当找到第一条birthday = '2023-12-01'的记录时,不确定后面还有没有这样的记录,所以必须继续往后找,直到遇到一条不是2023-12-01的记录未止。

间隙锁阻止其它事务插入,但是不阻止更新

情况二:范围查找

Session A Session B Session C
BEGIN;
SELECT * FROM t_user WHERE birthday >= '2023-11-11' AND birthday <='2023-11-28' FOR UPDATE;
   
 

UPDATE t_user SET score = score + 1 WHERE birthday = '2023-11-29';

Affected rows: 0

 
   

INSERT INTO t_user (id,`name`,id_card_no,birthday,score) VALUES (13,'华雄','1033','2023-11-29',1);

1205 - Lock wait timeout exceeded; try restarting transaction

MySQL InnoDB加锁规则分析

主键索引上加锁范围:id=30和id=40

辅助索引idx_birthday上加锁范围:(2023-01-01, 2023-11-12]、(2023-11-12, 2023-11-28]、(2023-11-28, 2023-11-30]

2.4.  不走索引

Session A Session B Session C
BEGIN;
SELECT * FROM t_user WHERE score = 2 FOR UPDATE;
   
 

UPDATE t_user SET score = score + 1 WHERE id = 33;

Affected rows: 0

 
   

INSERT INTO t_user (id,`name`,id_card_no,birthday,score) VALUES (33,'颜良','1038','2023-12-20',1);

Lock wait timeout exceeded; try restarting transaction

MySQL InnoDB加锁规则分析

在所有记录的主键上加next-key锁

加锁范围:(-∞, 10]、(10, 20]、(20, 30]、(30, 40]、(40, 50]、(50, +∞)

3.  总结

1、主键索引

  • 等值查询,命中,则被命中的主键索引加记录锁
  • 等值查询,未命中,则继续向后(向右)查找,直到找到第一个不满足的记录,对该记录加间隙锁,即锁住该记录之前的间隙,以防止其它事务向其中插入数据
  • 范围查找,找到的(满足条件的)记录的主键加记录锁,扫描过的区间加间隙锁

2、非主键唯一索引

  • 与主键索引类似,唯一的区别是锁住辅助索引记录的同时会锁住对应的主键索引

3、非唯一索引

  • 向右查找直到遇到一条不满足条件的记录,然后对扫描到的区间加间隙锁,对扫描到的辅助索引记录加记录锁,同时对与其对应的主键加记录锁

4、不走索引

  • 表中所有记录的主键加next-key锁

 

总结几个规律:

  1. 命中的索引记录会加记录锁,如果它是一个辅助索引,则对应的主键索引也会被加上记录锁
  2. 没有命中的记录不会被加记录锁
  3. 非唯一索引上查找时,当找到第一条满足条件的索引记录时,还会继续向右查找,直到遇到一条不满足条件的记录(PS:幸亏索引是有序的,不然找到累死)
  4. 当一条SQL没有走索引时,那么将会在每一条聚集索引上加X锁,这个类似于表锁,但原理上和表锁是完全不同的

建议:

  1. 尽量控制事务大小,减少锁定资源量和时间长度
  2. 即便在条件中使用了索引字段,但是否使用索引来检索数据是由 MySQL 通过判断不同执行计划的代价来决定的。如果 MySQL 认为全表扫描效率更高,它就不会使用索引。因此,在分析锁冲突时,可以查看执行计划(explain)以确认是否真正使用了索引

最后,重要的事情说三遍:

  • 加锁的单位是next-key锁
  • 加锁的单位是next-key锁
  • 加锁的单位是next-key锁

 

参考

https://www.cnblogs.com/harda/p/16820592.html

https://blog.csdn.net/qq_42604176/article/details/115431744

https://zhuanlan.zhihu.com/p/378306056

https://cloud.tencent.com/developer/article/1971381

https://cloud.tencent.com/developer/article/1844928文章来源地址https://www.toymoban.com/news/detail-760306.html

到了这里,关于MySQL InnoDB加锁规则分析的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MySQL基础(三十二)事务基础知识

    1.1 存储引擎支持情况 SHOW ENGINES 命令来查看当前 MySQL 支持的存储引擎都有哪些,以及这些存储引擎是否支持事务。 能看出在 MySQL 中,只有InnoDB 是支持事务的。 1.2 基本概念 事务 :一组逻辑操作单元,使数据从一种状态变换到另一种状态。 事务处理的原则 :保证所有事务都

    2024年02月05日
    浏览(33)
  • MySQL的基础知识

    数据: 描述事物符号记录。(包括数字、文字、图形、图像、声音、档案记录等)以记录形式统一的格式进行存储。 程序的概念 程序=指令+数据 狭义的数据和广义数据 狭义的数据(文字和符号记录)   结构化数据:文字、数字、符号记录被称为结构化数据,有一定的结构,

    2024年04月24日
    浏览(20)
  • 【MySQL】基础知识(二)

    衔接上文 MySQL基础知识(一),我们已经了解以下相关知识。 一个数据库服务器上,可以把很多有业务联系上的表放到一起,构成了一个逻辑上的“数据集合”,称为数据库。 数据库操作: 创建数据库 查看数据库 选中指定的数据库 删除数据库 那么下面我们继续来聊,MySQL的基

    2024年02月10日
    浏览(31)
  • MySQL 基础知识(十)之 MySQL 架构

    目录 1 MySQL 架构说明 2 连接层 3 核心业务层 3.1 查询缓存 3.2 解析器 3.3 优化器 3.4 执行器 4 存储引擎层 5 参考文档 1 MySQL 架构说明 下图是 MySQL 5.7 及其之前版本的逻辑架构示意图 MySQL 架构大致可分为以下三层: 连接层:负责跟客户端建立连接、获取权限、维持和管理连接 核

    2024年02月20日
    浏览(36)
  • MySQL 事务的基础知识

    事务是数据库区别于文件系统的重要特性之一,当我们有了事务就会让数据库中的数据始终保持 一致性 ,同时我们还能通过事务的机制 恢复到某个时间地点的数据 ,这样可以保证已提交到数据库的修改不会因为系统崩溃而丢失。 查询当前 MySQL 支持的存储引擎 Engine Support

    2024年02月04日
    浏览(30)
  • MySQL数据库基础知识,基础操作详细整理

    引入: 淘宝网,京东、微信,抖音等都有各自的功能,那么当我们退出系统的时候,下次再访问时,为什么信息还存在? 数据库(Database)是按照数据结构来组织、存储和管理数据的仓库。 每个数据库都有一个或多个不同的 API 用于创建,访问,管理,搜索和复制所保存的数

    2024年04月17日
    浏览(42)
  • 静态时序分析 第二章 基础知识

    目录 1. 逻辑门单元 2. 门单元的时序计算参数         2.1 信号转换延时(transition delay)          2.2 逻辑门延时(logic gate delay) 3.  时序单元相关约束         3.1 建立时间(setup time)         3.2 保持时间(hold time)         3.3 恢复时间         3.4 移除时间      

    2023年04月13日
    浏览(29)
  • MySQL 基础知识(九)之视图

    目录 1 视图的介绍 2 视图算法 3 创建视图 4 查看视图结构 5 修改视图 6 删除视图 7 参考文档 1 视图的介绍          视图是一张并不存储数据的虚拟表,其本质是根据 SQL 语句动态查询数据库中的数据。数据库中只存放了视图的定义,通过 SQL 语句使用视图时,会根据视图

    2024年02月19日
    浏览(23)
  • 【MySQL】数据库MySQL基础知识与操作

    作者主页:paper jie_博客 本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。 本文录入于《MySQL》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将MySQL基础知识一网打尽,希望可以帮到读者们哦。 其他专栏:《算法详解

    2024年02月05日
    浏览(33)
  • 嵌入式系统入门基础知识分析(一)

      目录 ​编辑 一、什么是嵌入式 二、嵌入式系统的组成 三、实时系统 四、实时系统的调度 五、嵌入式微处理器体系结构 六、逻辑电路基础 七、总线电路及信号驱动 八、电平转换电路 九、嵌入式系统中信息表示与运算基础 十、差错控制编码 十一、嵌入式系统的度量项目

    2024年02月05日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包