09_行级锁的加锁流程

news2024/9/28 12:43:43

MySQL 的加锁流程

文章目录

    • MySQL 的加锁流程
        • 简介
        • 记录锁、间隙锁和临键锁概述
        • 行级锁加锁流程
        • 示例流程
        • 两个原则,两个优化,一个 BUG
          • 两个原则
          • 两个优化
          • 一个 BUG
          • 示例1-主键(唯一)索引
          • 示例 2-普通索引
        • 总结

简介

在 MySQL InnoDB 存储引擎中,行级锁主要包括记录锁、间隙锁和临键锁。每种锁在不同的场景下用于确保数据的一致性和完整性。本文主要结合记录锁、间隙锁和临键锁来说明一下行级锁的加锁原理。

表级锁会直接锁表,一个事务加了锁,其余事务就要等待,所以表级锁不做过多介绍。


记录锁、间隙锁和临键锁概述
  1. 记录锁(Record Lock):锁定特定的索引记录。主要用于精确匹配的查询,防止其他事务修改该记录。
  2. 间隙锁(Gap Lock):锁定索引记录之间的间隙。用于防止其他事务在该间隙中插入新记录,从而避免幻读现象。
  3. 临键锁(Next-Key Lock):记录锁和间隙锁的组合。锁定一个索引记录及其前后的间隙,防止其他事务对这些范围内的数据进行插入、更新或删除操作。

行级锁加锁流程

在 InnoDB 中,加锁流程取决于查询类型和隔离级别。以下是结合记录锁、间隙锁和临键锁的行级锁加锁流程:

  1. 确定锁的类型和范围
    • 精确匹配查询(点查询):使用记录锁。例如,SELECT * FROM table WHERE id = 1 FOR UPDATE
    • 范围查询:使用临键锁。例如,SELECT * FROM table WHERE id BETWEEN 1 AND 10 FOR UPDATE
    • 唯一索引插入检查:可能使用间隙锁。
  2. 开始事务:启动一个事务。
  3. 请求锁
    • 记录锁:如果查询是精确匹配查询,InnoDB 在对应的索引记录上加记录锁(X 锁或 S 锁)。
    • 间隙锁:如果涉及唯一索引插入检查或需要防止幻读,InnoDB 在必要的间隙上加间隙锁。
    • 临键锁:如果是范围查询,InnoDB 在查询范围内的每个索引记录及其前后的间隙上加临键锁。
  4. 检查锁的兼容性
    • 记录锁:检查目标记录是否已经被其他事务锁定。如果锁类型不兼容(例如,已有 X 锁),当前事务需等待。
    • 间隙锁:检查目标间隙是否被其他事务锁定。如果已有间隙锁,且锁类型不兼容,当前事务需等待。
    • 临键锁:检查目标范围内的索引记录及其前后的间隙是否被其他事务锁定。如果锁类型不兼容,当前事务需等待。
  5. 加锁
    • 成功通过锁的兼容性检查后,InnoDB 在目标记录或间隙上加锁。
    • 更新 InnoDB 内部锁管理数据结构,记录锁的持有者和锁的类型。
  6. 执行查询或修改操作:在持有锁的情况下执行查询或修改操作。保证数据一致性。
  7. 提交或回滚事务
    • 提交事务:释放当前事务持有的所有锁。
    • 回滚事务:撤销当前事务的所有修改,并释放所有锁。

示例流程

以下是一个详细的示例流程,假设我们有一个表 example

CREATE TABLE example (
    id INT PRIMARY KEY,
    value VARCHAR(50)
);
INSERT INTO example (id, value) VALUES (1, 'A'), (2, 'B'), (3, 'C');

场景 1:精确匹配查询

  1. 事务 A

    START TRANSACTION;
    SELECT * FROM example WHERE id = 1 FOR UPDATE;  -- 对 id=1 加记录锁(X 锁)
    
  2. 事务 B

    START TRANSACTION;
    SELECT * FROM example WHERE id = 1 FOR UPDATE;  -- 被阻塞,直到事务 A 提交或回滚
    

场景 2:范围查询

  1. 事务 A

    START TRANSACTION;
    SELECT * FROM example WHERE id BETWEEN 1 AND 3 FOR UPDATE;  -- 对 id=1, id=2, id=3 及其间隙加临键锁
    
  2. 事务 B

    START TRANSACTION;
    INSERT INTO example (id, value) VALUES (2.5, 'D');  -- 被阻塞,直到事务 A 提交或回滚
    

场景 3:唯一索引插入检查

  1. 事务 A

    START TRANSACTION;
    INSERT INTO example (id, value) VALUES (4, 'D');  -- 插入成功,加间隙锁防止其他事务插入相同的 id
    
  2. 事务 B

    START TRANSACTION;
    INSERT INTO example (id, value) VALUES (4, 'E');  -- 被阻塞,直到事务 A 提交或回滚
    

两个原则,两个优化,一个 BUG

丁奇大佬在他的《MySQL 实战 45 讲》中总结了一些加锁规则,包含了两个原则,两个优化,一个 BUG。

两个原则
  • 原则 1:加锁的基本单位是临键锁(Next-Key Lock),是一个左开右闭的区间。
  • 原则 2:查找过程中访问到的对象才会加锁。
两个优化
  • 优化 1:索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。
  • 优化 2:索引上的等值查询,向右遍历时且最后一个值不满足等值条件的时候,next-key lock 退化为间隙锁。
一个 BUG
  • 唯一索引上的范围查询会访问到不满足条件的第一个值为止。
示例1-主键(唯一)索引

假如数据库表中有以下记录:

在这里插入图片描述

当我们执行 update t set d=d+1 where id=7 的时候,由于表 t 中没有 id=7 的记录,所以:

  • 根据原则1,加锁单位是 next-key lock, session A 加锁范围就是 (5,10];
  • 根据优化 2,这是一个等值查询 (id=7),而 id=10 不满足查询条件,next-key lock 退化成间隙锁,因此最终加锁的范围是(5,10)。

当我们执行 select * from t where id>=10 and id<11 for update 的时候:

  • 根据原则1,加锁单位是 next-key lock,会给(5,10]加上 next-key lock,范围查找就往后继续找,找到 id=15 这一行停下来;
  • 根据优化 1,主键id 上的等值条件,退化成行锁,只加了 id=10这一行的行锁。
  • 根据原则 2,访问到的都要加锁,因此需要加 next-key lock(10,15]。因此最终加的是行锁 id=10 和 next- key lock(10,15]。

当我们执行 select *from t where id>10 and id<=15 for update 的时候:

  • 根据原则 1,加锁单位是 next-key lock, 会给 (10,15] 加上 next-key lock, 并且因为 id 是唯一键,所以循环判断到 id=15 这一行就应该停止了。
  • 但是,InnoDB 会往前扫描到第一个不满足条件的行为止,也就是 id=20。而且由于这是个范围扫描,因此索引 id 上的(15,20]这个 next-key lock 也会被锁上。
示例 2-普通索引

假如数据库表中有以下记录:

在这里插入图片描述

当我们执行 select id from t where c=5 Lock in share mode 的时候:

  • 根据原则1,加锁单位是 next-key lock,因此会给(0,5]加上 next-key lock。要注意c是普通索引,因此仅访问 c=5 这一条记录是不能马上停下来的,需要向右遍历,查到 c=10 才放弃;
  • 根据原则 2,访问到的都要加锁,因此要给(5,10]加 next-key lock;
  • 根据优化 2:等值判断,向右遍历,最后一个值不满足 c=5 这个等值条件,因此退化成间隙锁 (5,10);
  • 根据原则2,只有访问到的对象才会加锁,这个查询使用覆盖索引,并不需要访问主键索引,所以主键索引上没有加任何锁。

当我们执行 select * from t where c>=10 and c<11 for update 的时候:

  • 根据原则1,加锁单位是 next-key lock,会给(5,10]加上 next-key lock,范围查找就往后继续找,找到 id=1,5 这一行停下来;
  • 根据原则 2,访问到的都要加锁,因此需要加 next-key lock(10,15];
  • 由于索引 c 是非唯一索引,没有优化规则,也就是说不会蜕变为行锁,因此最终 sesion A 加的锁是,索引上的(5,10]和(10,15] 这两个 next-key lock。

总结

MySQL 的 InnoDB 引擎下的 RR(Repeatable Read) 级别中,加锁的基本单位是临键锁(Next-Key Lock),只要扫描到的数据都会被加锁,唯一索引上的范围查询会访问到不满足条件的第一个为止。

通过记录锁、间隙锁和临键锁的配合,InnoDB 能够有效地管理并发事务,防止数据不一致和幻读现象。这些锁的加锁流程确保了在不同的查询和修改操作中,事务之间能够协调进行,提供了高效的并发控制和数据保护机制。在设计高并发系统时,理解和正确使用这些锁有助于提升系统的性能和可靠性。

引入这些锁,虽然一定程度上可以解决很多如幻读这样的问题,但是也会带来一些副作用,比如并发度降低和死锁等。当然,为了提升性能和并发度,也有两个优化点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2167393.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

理解C语言之深入理解指针(三)

目录 1. 字符指针变量 2. 数组指针变量 2.1 数组指针变量是什么&#xff1f; 2.2 数组指针变量怎么初始化 3. ⼆维数组传参的本质 4. 函数指针变量 4.1 函数指针变量的创建 4.2 函数指针变量的使⽤ 4.3 两段有趣的代码 4.3.1 typedef 关键字 5. 函数指针数组 6. 转移…

Linux递归找出目录下最近被修改文件(最近一段时间内被修改过的最新文件)(最近修改文件、最新文件、查找文件)(监控目录、监控mysql文件)

文章目录 命令1&#xff1a;找出目录下最近60分钟内修改的最新文件命令解析&#xff1a; 命令2&#xff1a;找出目录下最近60分钟内修改的最新n个文件 命令1&#xff1a;找出目录下最近60分钟内修改的最新文件 find /ky_data/mysql -type f -mmin -60 -exec ls -ltr {} | tai…

【LeetCode每日一题】——LCP 51.烹饪料理

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【解题思路】八【时间频度】九【代码实现】十【提交结果】 一【题目类别】 回溯 二【题目难度】 简单 三【题目编号】 LCP 51.烹饪料理 四【题目描述】 欢迎各位勇者来…

【工具分享】NoWay勒索病毒解密工具

前言 NoWay勒索软件首次出现在2023年&#xff0c;并迅速引起了网络安全领域的关注。它是一种典型的加密勒索软件&#xff0c;主要通过恶意电子邮件附件或不安全的下载链接传播。一旦成功感染系统&#xff0c;NoWay会加密受害者的文件&#xff0c;并要求支付赎金以恢复文件访问…

Redis(初步认识和安装)

初识Redis 认识NoSQLSQL结构化&#xff1a;structure关联的&#xff1a;RelationalSQL查询ACID NoSQL非结构化无关联的非SQLBASE 认识Redis安装Redis 认识NoSQL SQL和NoSQL比较 SQL 结构化&#xff1a;structure 数据库中表的字段都有固定的结构 关联的&#xff1a;Relati…

【c语言数据结构】栈的详解! 超级详细!(模拟实现,OJ练习题)

栈的概念&#xff1a; 栈&#xff1a;像是一种容器&#xff0c;东西只能从一个地方进&#xff0c;一个地方出&#xff0c;且后进先出&#xff01;这是其和队列&#xff08;先进先出&#xff0c;像排队一样&#xff0c;先到先得&#xff09;的本质区别 ⼀种特殊的线性表&#…

“JY901传感器“学习笔记

目录 一、产品概述 二、产品功能介绍 2.1、轴向说明 2.2、模块校准 2.3、姿态角 2.4、大地坐标系、地心地固坐标系、站心坐标系 三、参考文献 一、产品概述 模块集成高精度的陀螺仪、加速度计、地磁场传感器&#xff0c;采用高性能的微处理器和先进的动力解算与卡尔曼动…

两种不同方式实现交换机路由器的登录Console+Telnet的实现

一、背景及原理 1.Telnet 作为一种远程登录协议,1969年发明诞生于美国国防部高级研究计划局网络工作小组的研究员,Tenlet的出现为后续相关技术的发展奠定了基础。 2.Telnet通常用于远程登录应用中,对本地和远端进行网络设备配置、监控、维护,可以通过Telnet方式在一台设备…

博睿数据受邀亮相NebulaGraph Meetup北京站

9 月 21 日&#xff0c;北京站 nMeetup 如期而至&#xff0c;一场以 GraphRAG 和人工智能技术融合为主题的开发者聚会&#xff0c;在金秋的首都拉开帷幕。8 位讲师和 140 多位来自五湖四海的行业伙伴们相聚一堂&#xff0c;共同探讨 GraphRAG & AI 的最新发展和应用实践&am…

卷轴模式:一种新型的电子商务营销策略

随着电子商务行业的蓬勃发展&#xff0c;各类创新营销策略层出不穷&#xff0c;旨在吸引更多消费者并提升销售额。在这之中&#xff0c;卷轴模式以其独特的优势和可观的收益逐渐受到业界renxb001的关注。本文将深入探讨卷轴模式的概念、优势、应用场景以及如何参与其中。 卷轴…

关联式容器——map与set

map与set map与set的使用序列式容器与关联式容器概念序列式容器 (Sequence Containers)常见的序列式容器&#xff1a; 关联式容器 (Associative Containers)常见的关联式容器&#xff1a; set的定义与使用set类的介绍set的构造和迭代器set的增删查&#xff08;无改&#xff09;…

Ego微商小程序项目实战4.0【环境搭建】

✨博客主页&#xff1a; https://blog.csdn.net/m0_63815035?typeblog &#x1f497;《博客内容》&#xff1a;.NET、Java.测试开发、Python、Android、Go、Node、Android前端小程序等相关领域知识 &#x1f4e2;博客专栏&#xff1a; https://blog.csdn.net/m0_63815035/cat…

自动化测试框架集成:将Selenium集成到pytest与unittest中

目录 引言 一、Selenium简介 二、Selenium与pytest的集成 1. 安装pytest和Selenium 2. 编写测试用例 3. 运行测试 三、Selenium与unittest的集成 1. 编写测试类 2. 运行测试 四、Selenium自动化测试的最佳实践 1. 使用Page Object模式 2. 合理利用等待机制 3. 跨浏…

vioovi视与视标准工时工具与ECRS工时分析软件:精益生产的新纪元

在当今快速变化的市场环境中&#xff0c;企业面临着前所未有的挑战&#xff0c;其中成本控制与效率提升成为制约其发展的关键因素。传统的标准工时工具在应对这些挑战时显得力不从心&#xff0c;其局限性日益凸显。而vioovi视与视标准工时工具的出现&#xff0c;则为企业实现精…

西门子触摸屏下载时提示缺少面板映像的解决方法汇总

西门子触摸屏下载时提示缺少面板映像的解决方法汇总 使用V15/V15.1/V16/V17/V18/V19下载精智(Comfort)系列屏的项目时有时会提示“由于缺少面板映像,下载失败。请安装缺少的面板映像”,造成上述异常的主要原因是V15/V15.1/V16/V17/V18/V19的软件缺少对应的映像文件。常见问题…

《Linux从小白到高手》开篇:脱胎换骨之为什么要深度学习Linux?

List item 这一篇字数比较多&#xff0c;可能会比较枯燥。但是&#xff0c;如果你想学习Linux或者你想进一步提升自己的Linux专业水平&#xff0c;那么&#xff0c;还是请你坚持看完。这倒不是说文笔有多好&#xff0c;而是作为一个学习并使用了Linux 十多年的老司机&#xff…

PHP Swoole 基本使用

背景 在项目中&#xff0c;我们使用了PHP语言&#xff0c;但由于存在长耗时的任务&#xff0c;所以需要服务器端异步响应。为了实现异步响应&#xff0c;我们有多种方案可选&#xff0c;包括MQ&#xff08;消息队列&#xff09;、fsocket&#xff08;文件套接字&#xff09;、…

【Redis】渐进式遍历 数据库管理命令 RESP协议

目录 渐进式遍历 scan 数据库管理命令 切换数据库 获取当前数据库key的个数 删除当前数据库所有的key 删除所有数据库中所有的key RESP协议 渐进式遍历 Redis使用scan命令进行渐进式遍历键&#xff0c;进而解决直接使用keys获取键时可能出现的阻塞问题&#xff08;因为…

多旋翼无人机光伏发电站吊运技术详解

随着清洁能源技术的快速发展&#xff0c;光伏发电站作为可再生能源的重要组成部分&#xff0c;其建设与维护对效率、安全性和成本控制的要求日益提高。多旋翼无人机光伏发电站吊运技术应运而生&#xff0c;该技术利用多旋翼无人机强大的垂直起降能力、灵活的飞行控制以及高效的…

CSS中的字体样式、文本样式、列表样式以及背景和渐变

一、字体样式和文本样式 1.span标签 span标签的作用&#xff1a;能让某几个文字或者是词语凸显出来 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-…