首页 > 数据库 >mysql InnoDB引擎各种隔离级别的加锁机制

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

时间:2024-08-22 12:53:07浏览次数:14  
标签:加锁 name -- age stu InnoDB mysql id

文章目录

概要

我们都知道,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隔离级别下加在非唯一索引的两个数据之间的锁,注意是非唯一索引,理论上我们对主键索引去修改数据时是不会加间隙锁的。注意间隙锁只有在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锁的锁定范围这些

标签:加锁,name,--,age,stu,InnoDB,mysql,id
From: https://blog.csdn.net/m0_37903574/article/details/141422010

相关文章

  • MySQL 亿级数据平滑迁移实战
    作者:来自vivo互联网服务器团队-LiGang本文介绍了一次MySQL数据迁移的流程,通过方案选型、业务改造、双写迁移最终实现了亿级数据的迁移。一、背景预约业务是vivo游戏中心的重要业务之一。由于历史原因,预约业务数据表与其他业务数据表存储在同一个数据库中。当其他业务......
  • MYSQL长事务排查
    查看造成等待的事务执行SQLSELECTtmp.waiting_thread'等待线程ID',tmp.waiting_trx_id'等待事务ID',tmp.wating_trx_state等待事务状态,tmp.waiting_query等待语句,case when(tmp.waiting_time-28800)>0then(tmp.waiting_time-28800) elsetmp......
  • Prometheus+Grafana监控Mysql数据库
    安装配置Prometheus是Go语言编写的,所以仅依赖二进制编译库,从官网根据操作系统下载对应的二进制库:https://prometheus.io/download/解压到/usr/local/prometheus目录下tar-xzvfprometheus-2.45.2.linux-amd64.tar.gzmvprometheus-2.45.2.linux-amd64/usr/local/prometheus......
  • 深入探索分布式任务调度框架:MySQL实现高效锁机制
    本文主要介绍项目中怎么使用MySQL实现分布式锁的背景假如我们现在要做一个高性能、可扩展的分布式任务调度框架,要怎么设计呢?下面是我之前自己设计的一个架构图。为了方便后续的分布式锁的设计,我们大致描述下各个角色都做了哪些事情(这不是本篇文章的重点)scheduler-c......
  • Mysql锁查看
    查看InnoDB的锁情况SHOWENGINEINNODBSTATUS;命令会返回一个包含详细InnoDB引擎状态的报告,其中包含当前锁的详细信息。在输出的LATESTDETECTEDDEADLOCK部分找到死锁信息,并在TRANSACTIONS部分找到当前的锁等待信息。查看MyISAM锁情况--方法一:查看表锁SHOWOPEN......
  • Mac导出Mysql千万级表数据
    MysqlDumpmysqldump-h[服务器地址]-u[用户名]-p[密码]--single-transaction--quick[数据库名][表名]>[导出文件.sql]•--single-transaction保证了数据的一致性,并且不会在导出期间锁定表(只针对InnoDB有效)。•--quick选项进一步减少了内存使用,因为它逐行导出数......
  • Windows-安装MySQL数据库
    mysql安装:11.将zip包解压到指定目录,例如:D:\tools\mysql-8.0.18-winx64注:不放到C硬盘,win10系统权限不够会报错,麻烦2.复制改变my.ini文件放在目录:D:\tools\mysql-8.0.18-winx64\bin,并添加相关配置(给的文件中配置内容已经都有了)注1:my.ini配置文件里面非注释语句不要有“”双引......
  • 京东面试:mysql分库分表,深度翻页太慢,如何解决
    京东面试:mysql分库分表,深度翻页太慢,如何解决?在40岁老架构师尼恩的读者交流群(50+)中,最近有小伙伴拿到了一线互联网企业如得物、阿里、滴滴、极兔、有赞、shein希音、shopee、百度、网易的面试资格,遇到很多很重要的面试题:mysql分库分表,深度翻页太慢,如何解决?分库分表后,分页......
  • MySQL基本数据类型
    MySQL数据类型MySQL中定义数据字段的类型对你数据库的优化是非常重要的。MySQL支持多种类型,大致可以分为三类:数值、日期/时间和字符串(字符)类型。数值类型MySQL支持所有标准SQL数值数据类型。这些类型包括严格数值数据类型(INTEGER、SMALLINT、DECIMAL和NUMERIC),以......
  • 银河麒麟系统V10(arm版)安装Mysql-5.7.29说明
    #银河麒麟系统适配#随着2024年微软全球蓝屏丑闻的出现,系统安全越来越重要。目前很多企业开始尝试国产化操作系统上,本文介绍如何在国产化银河麒麟系统V10(arm)版上安装mysql。本资源使用的是arm版本的Mysql-5.7.29离线安装包,能够在arm版国产化银河麒麟系统上进行安装,并配置防火......