MySQL锁三部曲:临键、间隙与记录的奇妙旅程

欢迎来到我的博客,代码的世界里,每一行都是一个故事


在这里插入图片描述

MySQL锁三部曲:临键、间隙与记录的奇妙旅程

    • 前言
    • 临键锁的奥秘
    • 间隙锁
    • 记录锁

前言

在数据库世界中,锁是维护数据完整性的一种关键机制。而MySQL中的临键锁、间隙锁和记录锁则是锁定数据的三大法宝。本文将引领读者进入这场锁的盛宴,深刻理解这三种锁的独特作用,以及如何在实际应用中灵活运用它们。

临键锁的奥秘

临键锁(Next-Key Locks)是很独特的一种锁,直观上来说可以看做是一个记录锁和间隙锁的组合。也就是说临键锁不仅仅是会用记录锁锁住命中的记录,也会用间隙锁锁住记录之间的空隙。临键锁和数据库隔离级别的联系最为紧密,它可以解决在可重复读隔离级别之下的幻读问题。间隙锁是左开右开,而临键锁是左开右闭。在数据库中,“临键锁"通常指的是"临键锁定”(Row-level lock),这是一种锁定记录的机制,确保对特定记录的独占访问。以下是临键锁的基本概念以及在数据库中如何使用它来确保对特定记录的独占访问:

基本概念:

  1. 行级锁: 临键锁是行级锁的一种,它锁定表中的特定行而不是整个表。

  2. 锁粒度: 行级锁允许并发事务在表中的不同行上工作,从而提高系统的并发性。

  3. 锁的状态: 临键锁可以处于不同的状态,包括共享锁(Shared Lock)和独占锁(Exclusive Lock)。

  4. 共享锁和独占锁:

    • 共享锁: 允许多个事务同时获取锁,用于读取操作,表示事务不会修改数据。
    • 独占锁: 只允许一个事务获取锁,用于写入操作,表示事务可能修改数据。

在数据库中如何使用临键锁:

  1. SELECT语句中的共享锁:

    • 当事务执行SELECT语句时,可以使用共享锁来确保其他事务不会在相同的记录上执行写操作。
    • 通过使用SELECT … FOR SHARE语法,事务可以获取共享锁。
    SELECT * FROM your_table WHERE your_condition FOR SHARE;
    
  2. UPDATE和DELETE语句中的独占锁:

    • 当事务执行UPDATE或DELETE语句时,可以使用独占锁来确保其他事务不会同时修改或删除相同的记录。
    • 通过使用UPDATE或DELETE语句时的FOR UPDATE语法,事务可以获取独占锁。
    UPDATE your_table SET your_column = 'new_value' WHERE your_condition FOR UPDATE;
    
  3. INSERT语句中的独占锁:

    • 当事务执行INSERT语句时,可以使用独占锁来确保其他事务不会同时在相同的记录位置插入数据。
    • 通过使用INSERT … ON DUPLICATE KEY UPDATE或INSERT IGNORE语句时的FOR UPDATE语法,事务可以获取独占锁。
    INSERT INTO your_table (your_columns) VALUES (your_values) ON DUPLICATE KEY UPDATE your_column = 'new_value' FOR UPDATE;
    

通过合理使用临键锁,可以在多个并发事务中确保对数据库表中特定记录的独占访问,从而维护数据的一致性和完整性。需要注意的是,过度使用锁可能导致性能问题,因此在设计和优化时需要权衡并考虑具体的业务场景。

间隙锁

间隙锁的作用:

间隙锁(Gap Lock)是一种在数据库中用于锁定一个范围而不是单个记录的锁。其作用在于:

  1. 确保范围内没有新数据插入: 通过使用间隙锁,可以确保在一个范围内没有新的记录被插入,从而避免并发事务在同一个范围内插入新的数据。

  2. 防止幻读: 间隙锁也可以防止幻读,即在同一个范围内确保其他事务不会插入新的记录,防止当前事务读到其他事务插入的未提交数据。

在并发操作中如何使用间隙锁:

考虑以下情境,使用间隙锁来避免不可预知的问题:

  1. 事务1:

    START TRANSACTION;
    SELECT * FROM your_table WHERE your_column BETWEEN 10 AND 20 FOR UPDATE;
    
  2. 事务2:

    START TRANSACTION;
    -- 此时间隙锁会锁定范围 [10, 20],防止其他事务插入新数据
    INSERT INTO your_table (your_column) VALUES (15);
    COMMIT;
    
  3. 事务1:

    -- 在此时,事务1再次执行相同的查询
    SELECT * FROM your_table WHERE your_column BETWEEN 10 AND 20 FOR UPDATE;
    

在上述例子中,如果没有间隙锁,事务1的第二次查询可能会读到事务2插入的新数据,导致不可预知的结果。通过使用FOR UPDATE和间隙锁,可以确保事务1在范围 [10, 20] 内的查询结果不会被其他事务插入新数据所影响。

需要注意的问题:

  1. 性能开销: 使用间隙锁可能会增加性能开销,因为它限制了其他事务在相同范围内插入数据。

  2. 并发控制: 间隙锁在一些情况下可能导致并发控制的降低,因此在设计时需要权衡并考虑具体的业务场景。

  3. 事务隔离级别: 间隙锁的行为可能会受到事务隔离级别的影响,需要谨慎选择适当的隔离级别。

在并发操作中,使用间隙锁能够确保对特定范围内的记录进行独占性操作,从而维护数据的一致性和完整性。

记录锁

记录锁(Row-level lock)是一种锁定数据库表中单个记录的机制。它在事务中的实际应用场景中发挥关键作用,可以保护数据的完整性。以下是记录锁的实际应用场景以及在事务中如何使用记录锁的详细讨论:

实际应用场景:

  1. 更新操作:

    • 当一个事务要对某个记录进行更新时,可以使用记录锁确保其他事务不能同时修改相同的记录,防止并发更新导致数据不一致。
    -- 事务1
    START TRANSACTION;
    SELECT * FROM your_table WHERE your_condition FOR UPDATE;
    -- 执行更新操作
    UPDATE your_table SET your_column = 'new_value' WHERE your_condition;
    COMMIT;-- 事务2
    START TRANSACTION;
    SELECT * FROM your_table WHERE your_condition FOR UPDATE; -- 会等待事务1释放锁
    -- 执行更新操作
    UPDATE your_table SET your_column = 'another_value' WHERE your_condition;
    COMMIT;
    
  2. 插入操作:

    • 当一个事务要在某个范围内插入新记录时,可以使用记录锁防止其他事务在相同范围内插入数据,避免幻读问题。
    -- 事务1
    START TRANSACTION;
    SELECT * FROM your_table WHERE your_column BETWEEN 10 AND 20 FOR UPDATE;
    -- 执行插入操作
    INSERT INTO your_table (your_column) VALUES (15);
    COMMIT;-- 事务2
    START TRANSACTION;
    SELECT * FROM your_table WHERE your_column BETWEEN 10 AND 20 FOR UPDATE; -- 会等待事务1释放锁
    -- 执行插入操作
    INSERT INTO your_table (your_column) VALUES (18);
    COMMIT;
    
  3. 删除操作:

    • 当一个事务要删除某个记录时,可以使用记录锁确保其他事务不能同时访问和修改相同的记录。
    -- 事务1
    START TRANSACTION;
    SELECT * FROM your_table WHERE your_condition FOR UPDATE;
    -- 执行删除操作
    DELETE FROM your_table WHERE your_condition;
    COMMIT;-- 事务2
    START TRANSACTION;
    SELECT * FROM your_table WHERE your_condition FOR UPDATE; -- 会等待事务1释放锁
    -- 执行其他操作
    COMMIT;
    

注意事项:

  1. 记录锁是通过使用FOR UPDATE语句实现的,它会锁定查询结果集中的行,防止其他事务在同一行上执行写操作。

  2. 记录锁的使用需要谨慎,过度使用可能导致性能问题,因此在设计时需要根据实际情况进行权衡。

  3. 事务隔离级别的选择会影响记录锁的行为,需要根据业务需求选择合适的隔离级别。

  4. 记录锁的释放通常发生在事务提交时,因此事务的持有时间应该尽量短,以减小锁的粒度和持有时间。

在事务中使用记录锁可以确保并发事务对数据库表中的记录进行独占性操作,从而维护数据的完整性。

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

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

相关文章

Python零基础安装教程(包含各种安装方案)以及PyCharm安装步骤

文章目录 安装方案介绍安装Python解释器安装Pycharm安装Anaconda方案参考 安装方案介绍 方案1:只安装Python解释器(适合小型开发) 方案2:安装集成开发环境Anaconda(集成了Spyder,JupyterNotebook等编辑器&…

cmd命令开启windows桌面远程控制并设置防火墙允许远程

cmd命令开启桌面远程控制 1、开启之前: 2、使用管理员身份运行cmd 3、执行cmd命令 reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlset\Control\Terminal server" /v fDenyTSConnections /t REG_DWORD /d 0 /f4、如果这台电脑的防火墙打开&#xff…

【buuctf-我吃三明治】

看到这个题,我忽然感觉答案就在中间,三明治笑死了。这张原始 flag 图片包含两张图,为什么是两张图见下: 以FF D9结尾是第一张图片结束,FF D8 FF是第二张图片开始。 两张图片拆出来分别是下面两张(当然没什…

Spring Boo项目中方法参数对象中字段上存在的自定义注解如何进行拦截解析

一、前言 在Spring Boot项目开发过程中,我们经常会使用到自定义注解的方式进行业务逻辑开发,此时注解我们一般是放在方法或者类上面,通过AOP切面拦截的方式进行自定义业务逻辑填充。但是如果自定义注解放在类的字段上,此时应该如…

平头哥IP核C906的JTAG调试器DIY教程(一)

背景 最近买了一块基于平头哥C906核,SOC为全志的D1s,的核心板,手工焊接在白嫖的底板上(此处感谢百问网老师的友情支持,手动狗头)。在焊接完成后,进行点亮跑程序的时候,发现没有优雅…

Makefile静态库动态库的构建和链接之工程实用篇

静态库和动态库的构建和链接 现有C工程目录结构如下&#xff1a; add.h int add(int a, int b);add.cpp #include "add.h"int add(int a, int b) {return ab; }main.cpp #include <iostream> #include "add.h"int main() {std::cout << a…

GEE必须会教程—曾“几何”时(Geometry类型)

几何图形组成了世界万物&#xff0c;在数学史具有重要地位&#xff0c;将几何图形迁移到地理空间信息的处理上&#xff0c;我们我们得到就是研究区域的边界范围&#xff0c;因此&#xff0c;在学习矢量数据和栅格数据之前&#xff0c;我们有必要了解几何图形在GEE上的编辑。 1…

C语言——结构体——(第21篇)

坚持就是胜利 文章目录 一、结构体类型的声明1、结构的基础知识2、结构的声明3、结构成员的类型 二、结构体变量的定义和初始化结构体中包含结构体 三、结构体成员访问问题一&#xff1a;t.name "张三"&#xff0c;对吗&#xff1f;问题二&#xff1a;set_Stu(s);应…

C#与VisionPro联合开发——跳转页面

1、跳转页面并打开相机 From1 所有代码展示 using System; using System.IO; using System.Windows.Forms; //引入VisionPro命名空间 using Cognex.VisionPro;namespace ConnectCamera {public partial class Form1 : Form {public Form1() {InitializeComponent();}CogAcqFif…

Java核心-核心类与API(3)

话接上回&#xff0c;继续核心类与API的学习&#xff0c;这次介绍一下枚举类以及与系统、交互有关的类&#xff0c;需要了解并能使用即可。 一、枚举类 1、概述 枚举也称穷举&#xff0c;简单理解就是把所有可能一一列举出来&#xff08;穷尽所有可能&#xff09;。枚举是一…

前端学习——JS学习

文章目录 1. 定义变量&#xff0c;关键字 var、let、const2. 定义变量&#xff0c;数据类型3. 数组变量的操作4. 对象的操作5. JSON 字符串 1. 定义变量&#xff0c;关键字 var、let、const 这里主要是对var、let做比较 /** 1. var存在变量提升、let不存在变量提升 **/ cons…

【C语言基础】:操作符详解(一)

文章目录 操作符详解1. 操作符的分类2. 二进制和进制转换2.1 什么是二进制、八进制、十进制、十六进制2.1.1 二进制和进制转换2.1.2 二进制转十进制2.2.3 二进制转八进制2.2.4 二进制转十六进制 3. 源码、反码、补码4. 移位操作符4.1 左移操作符4.2 右移操作符 5. 位操作符&…

【域适应论文汇总】未完结

文章目录 DANN&#xff1a;Unsupervised Domain Adaptation by Backpropagation (2015)TADA&#xff1a;Transferable Attention for Domain Adaptation&#xff08;2019 AAAI&#xff09;1 局部注意力迁移&#xff1a;Transferable Local Attention2 全局注意力迁移&#xff1…

调度服务看门狗配置

查看当前服务器相关的sqlserver服务 在任务栏右键&#xff0c;选择点击启动任务管理器 依次点击&#xff0c;打开服务 找到sqlserver 相关的服务&#xff0c; 确认这些服务是启动状态 将相关服务在看门狗中进行配置 选择调度服务&#xff0c;双击打开 根据上面找的服务进行勾…

打开 Camera app 出图,前几帧图像偏暗、偏色该怎样去避免?

1、问题背景 使用的安卓平台&#xff0c;客户的应用是要尽可能快的获取到1帧图像效果正常的图片。 但当打开 camera 启动出流后&#xff0c;前3-5帧图像是偏暗、偏色的&#xff0c;如下图所示&#xff0c;是抓取出流的前25帧图像&#xff0c; 前3帧颜色是偏蓝的&#xff0c;…

vue2和vue3 setup beforecreate create生命周期时间比较

创建一个vue程序&#xff0c;vue3可以兼容Vue2的写法&#xff0c;很流畅完全没问题 写了一个vue3组件 <template><div></div> </template><script lang"ts"> import {onMounted} from vue export default{data(){return {}},beforeCr…

操作符详解3

✨✨ 欢迎大家来到莉莉的博文✨✨ &#x1f388;&#x1f388;养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; 前面我们已经讲过算术操作符、赋值操作符、逻辑操作符、条件操作符和部分的单目操作 符&#xff0c;今天继续介绍一部分。 目录 1.操作符的分类 2…

【软件测试面试】要你介绍项目-如何说?完美面试攻略...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、测试面试时&am…

QtRVSim F扩展实现(一):解码阶段

跟踪解码流程可以发现&#xff0c;解码主要是读取 instruction.cpp 里存储的指令集数组进行解码的。 那么对于实现 F 扩展指令集&#xff0c;第一步能成功读取识别新指令&#xff0c;就需要从这里入手。 解码部分代码&#xff1a; static inline const struct InstructionMa…

12. Springboot集成Dubbo3(三)Dubbo-Admin

目录 1、前言 2、安装 2.1、下载Dubbo-admin 2.2、修改配置 2.3、编译前端 2.4、访问 2.5、加载自己的服务 2.6、服务测试 2.7、其他 3、小结 1、前言 Dubbo Admin是用于管理Dubbo服务的基于Web的管理工具。Dubbo Admin提供了一个用户友好的界面&#xff0c;用于在分…