mysql InnoDB引擎各种隔离级别的加锁机制

2024-08-23 19:44

本文主要是介绍mysql InnoDB引擎各种隔离级别的加锁机制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 概要
    • 前置知识了解
    • 各种隔离锁的验证
    • 小结

概要

我们都知道,mysql的InnoDB引擎在各种隔离级别下的加锁机制都是有差异的,但是对于各种隔离级别下如何加锁大家可能不太了解,今天我就通过一篇文章去带领大家去分析一下各个隔离级别的加锁过程,如果有误,欢迎大家在评论区指正!

今天实验的表结构定义如下,欢迎大家自己去尝试验证。我的mysql版本是5.7。其中id加上了唯一索引为了验证行锁的加锁过程。age加上非唯一索引,给大家演示一下gap的加锁过程。:

-- 学生表,id,姓名,年纪三个字段。
CREATE TABLE `t_stu` (`id` bigint NOT NULL AUTO_INCREMENT COMMENT '商品ID',`name` varchar(64) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '会员卡名称',`age` int NOT NULL,PRIMARY KEY (`id`) USING BTREE,KEY `name` (`name`),KEY `age` (`age`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=78 DEFAULT CHARSET=utf8mb3 COMMENT='会员商品表';INSERT INTO `t_stu` (`id`, `name`, `age`) VALUES (1, '小张', 1);
INSERT INTO `t_stu` (`id`, `name`, `age`) VALUES (3, '小王', 3);
INSERT INTO `t_stu` (`id`, `name`, `age`) VALUES (4, '小美', 4);
INSERT INTO `t_stu` (`id`, `name`, `age`) VALUES (44, '小美', 44);

前置知识了解

读锁和写锁的互斥情况,只有读锁和读锁可以并行执行,其他的情况都是互斥的。

读锁写锁
读锁x
写锁xx
  • mysql的表级锁有哪些,其中我们需要重点关注的就是元数据锁:
    1. 表锁:通常意义上我们是不会给表主动加锁。通过 LOCK TABLES t_stu READ,LOCK TABLES t_stu WRITE去加锁。通过unlock tables去解锁。在实际的业务过程中题主暂时未遇到过使用场景,所以这个锁不在我们的讨论范围。
    2. 元数据锁(MDL):这个锁我们需要关注一下,我们在表结构变更时会加一个MDL写锁,就是当我们操作表做DDL语句时,例如:给表加字段,给表加索引。当我们给做crud语句时会给表加MDL读锁。所以在高并发的场景下,不可以去对表做DDL操作,会锁表。 因为DDL语句不会被事物控制,所以对于小批量的数据题主没办法演示加锁情况,大家可以自行多加点数据去做演示。
    3. 意向锁:题主没关注这个。
    4. AUTO-INC 锁:主键索引自增时加的一个锁。

  • mysql的行锁有哪些:
    1. 行级锁: 加在索引上的锁,如果表上没有任何索引,InnoDB会使用一个内部的行ID来锁定行。在RR隔离级别下,我们在没有索引的表上去修改数据,其实是锁定了所有的行+加上行的间隙,并不是锁表。
    2. 间隙锁 GAP LOCK: 间隙锁是RR隔离级别下加在非唯一索引的两个数据之间的锁,注意是非唯一索引,理论上我们对主键索引去修改数据时是不会加间隙锁的。另外一种情况就是where范围查询时,锁定主键索引的区间。注意间隙锁只有在RR隔离级别下才存在。
    3. next-key lock: 行级锁+间隙锁组成的锁。

各种隔离锁的验证

  • 读未提交 (READ UNCOMMITTED): 按照顺序执行,我们会发现事物2在执行到第四步时被阻塞了,说明在读未提交的情况下是有行级锁存在的。并不是网上说的行级锁只存在于读已提交和可重复读的隔离级别。
-- 事物1 ----------------------------------------------------------
-- 1
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN;
-- 3
UPDATE `t_stu` SET `name` = 'aa' WHERE `id` = 1;
COMMIT;-- 事物2 ----------------------------------------------------
-- 2
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
BEGIN;
-- 4
UPDATE `t_stu` SET `name` = 'aaa' WHERE `id` = 1;
COMMIT;

通过命令查看加锁状态,可以看到数据都被加了X锁,就是排它锁。
在这里插入图片描述
在这里插入图片描述

  • 读已提交 (READ COMMITTED):
-- 事物1 ----------------------------------------------------------
-- 1
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;
-- 3
-- UPDATE `t_stu` SET `name` = 'aa' WHERE `id` = 1;
SELECT * FROM `t_stu` WHERE age = 4 LOCK IN SHARE MODE;
-- 5
SELECT * FROM `t_stu` WHERE age = 4 LOCK IN SHARE MODE;
-- 7
COMMIT;-- 事物2 ----------------------------------------------------
-- 2
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
BEGIN;
-- 4
INSERT INTO `jl`.`t_stu` (`id`, `name`, `age`) VALUES (10, '小小美', 4);
-- 6
COMMIT;

注意这块的查询语句我加上了S共享锁,因为mysql默认查询时SELECT语句是默认不加锁的,所以为了方便演示我加上了读共享锁。上述语句我们在执行时,是能成功的插入数据的,通过锁分析也可得知在RC隔离级别下,对于普通索引的数据我们只加了行级锁,但是没有加gap lock的。当我们执行到步骤5,第六步未执行的情况下,我们看一下加锁状态,写请求加了X排它锁,读数据我加了共享锁。所以从分析就可以得知在RC隔离级别下,就算是普通的非唯一索引age,也不会加gap锁。

在这里插入图片描述

  • 可重复读 (REPEATABLE READ):
-- 事物1 ----------------------------------------------------------
-- 1
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
-- 3
-- UPDATE `t_stu` SET `name` = 'aa' WHERE `id` = 1;
SELECT * FROM `t_stu` WHERE age = 4 LOCK IN SHARE MODE;
-- 5
SELECT * FROM `t_stu` WHERE age = 4 LOCK IN SHARE MODE;
-- 7
COMMIT;-- 事物2 ----------------------------------------------------
-- 2
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
-- 4
INSERT INTO `jl`.`t_stu` (`id`, `name`, `age`) VALUES (10, '小小美', 4);
-- 6
COMMIT;

当我们在执行步骤4时其实就会被阻塞了,数据是没办法插入成功的,因为此时在age的的非唯一索引上加了age=4的数据的行级别锁,在非主键键索引上在age(3,4)(4,44)之间加了gap lock。导致了数据插入时就会锁冲突,没办法进行数据插入。
在这里插入图片描述
我们在演示一个其他的例子,我们把上面事物2的插入的id为10的age数据改成64。先看一数据库的数据:
在这里插入图片描述

-- 事物2 ----------------------------------------------------
-- 2
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
BEGIN;
-- 4
INSERT INTO `jl`.`t_stu` (`id`, `name`, `age`) VALUES (10, '小小美', 64);
-- 4
-- 6
COMMIT;

最终发现,执行到步骤4时,数据是可以插入成功的,那就是因为,我们age为64的数据不在gap锁锁定age的范围(3,4),(4,44)范围内。

小结

通过上面的各种的案例演示,给大家展示了各种隔离级别下的数据的加锁状态。可能有些知识点是打破可大家对于加锁状态的认知的,大家可以通过本地数据库去模拟一下各种隔离级别的数据加锁状态,会加深大家对于这些知识的认知:行锁什么时候加,gap锁什么时候加,gap锁的锁定范围这些

这篇关于mysql InnoDB引擎各种隔离级别的加锁机制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1100326

相关文章

MySQL 删除数据详解(最新整理)

《MySQL删除数据详解(最新整理)》:本文主要介绍MySQL删除数据的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录一、前言二、mysql 中的三种删除方式1.DELETE语句✅ 基本语法: 示例:2.TRUNCATE语句✅ 基本语

MySQL中查找重复值的实现

《MySQL中查找重复值的实现》查找重复值是一项常见需求,比如在数据清理、数据分析、数据质量检查等场景下,我们常常需要找出表中某列或多列的重复值,具有一定的参考价值,感兴趣的可以了解一下... 目录技术背景实现步骤方法一:使用GROUP BY和HAVING子句方法二:仅返回重复值方法三:返回完整记录方法四:

从入门到精通MySQL联合查询

《从入门到精通MySQL联合查询》:本文主要介绍从入门到精通MySQL联合查询,本文通过实例代码给大家介绍的非常详细,需要的朋友可以参考下... 目录摘要1. 多表联合查询时mysql内部原理2. 内连接3. 外连接4. 自连接5. 子查询6. 合并查询7. 插入查询结果摘要前面我们学习了数据库设计时要满

Spring事务传播机制最佳实践

《Spring事务传播机制最佳实践》Spring的事务传播机制为我们提供了优雅的解决方案,本文将带您深入理解这一机制,掌握不同场景下的最佳实践,感兴趣的朋友一起看看吧... 目录1. 什么是事务传播行为2. Spring支持的七种事务传播行为2.1 REQUIRED(默认)2.2 SUPPORTS2

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

mysql表操作与查询功能详解

《mysql表操作与查询功能详解》本文系统讲解MySQL表操作与查询,涵盖创建、修改、复制表语法,基本查询结构及WHERE、GROUPBY等子句,本文结合实例代码给大家介绍的非常详细,感兴趣的朋友跟随... 目录01.表的操作1.1表操作概览1.2创建表1.3修改表1.4复制表02.基本查询操作2.1 SE

MySQL中的锁机制详解之全局锁,表级锁,行级锁

《MySQL中的锁机制详解之全局锁,表级锁,行级锁》MySQL锁机制通过全局、表级、行级锁控制并发,保障数据一致性与隔离性,全局锁适用于全库备份,表级锁适合读多写少场景,行级锁(InnoDB)实现高并... 目录一、锁机制基础:从并发问题到锁分类1.1 并发访问的三大问题1.2 锁的核心作用1.3 锁粒度分

MySQL数据库中ENUM的用法是什么详解

《MySQL数据库中ENUM的用法是什么详解》ENUM是一个字符串对象,用于指定一组预定义的值,并可在创建表时使用,下面:本文主要介绍MySQL数据库中ENUM的用法是什么的相关资料,文中通过代码... 目录mysql 中 ENUM 的用法一、ENUM 的定义与语法二、ENUM 的特点三、ENUM 的用法1

MySQL count()聚合函数详解

《MySQLcount()聚合函数详解》MySQL中的COUNT()函数,它是SQL中最常用的聚合函数之一,用于计算表中符合特定条件的行数,本文给大家介绍MySQLcount()聚合函数,感兴趣的朋... 目录核心功能语法形式重要特性与行为如何选择使用哪种形式?总结深入剖析一下 mysql 中的 COUNT

mysql中的服务器架构详解

《mysql中的服务器架构详解》:本文主要介绍mysql中的服务器架构,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、背景2、mysql服务器架构解释3、总结1、背景简单理解一下mysqphpl的服务器架构。2、mysjsql服务器架构解释mysql的架