MySQL 锁概述

1.锁的分类

根据不同的分类角度可将锁分为:

  • 按是否共享分:S 锁、X 锁
  • 按粒度分:表级锁、行级锁、全局锁(锁整个库)、页锁(锁数据页)
  • 意向锁:意向 S 锁、意向 X 锁:都是表级锁,且 IS 和 IX 之间不互斥。IS 锁和 IX 锁的使命只是为了后续在加表级别的 S 锁和 X 锁时判断表中是否有已经被加锁的记录,以避免用遍历的方式来查看表中有没有上锁的记录。
  • MDL 锁(元数据锁)

InnoDB 的表级锁比较鸡肋,一般不会被用到,重点在于理解 InnoDB 的行级锁。

InnoDB 常见行级锁:

  • Record Locks(正经记录锁):可以加上 S 锁或 X 锁。
  • Gap Locks(间隙锁):用于防止数据插入,解决了可重复读隔离级别下幻读的问题。
  • Next-Key Locks(临键锁):等价于 正经记录锁 + 间隙锁
  • Insert Intention Locks(插入意向锁):其实就是 MySQL 的设计者规定事务发生时需要在内存中获取一个锁,而现在这个事务正好是为了插入数据,所以锁的类型就定为插入意向锁了。
  • 隐式锁:面对事务 T1 中插入了一条记录,该记录上没有任何锁。此时,其他的事务对该记录进行读写时就可能产生脏读或脏写的问题。为此,InnoDB 通过事务 id 来判断当前事务是否处于活跃状态,如果是处于活跃状态的,则会自动加上 X 锁。(因为写操作都会加 X 锁,所以写操作都是针对最新的记录的)

按锁的态度分:

  • 悲观锁:

    悲观锁是一种思想,顾名思义,就是很悲观,对数据被其他事务的修改持保守态度,会通过数据库自身的锁机制来实现,从而保证数据操作的排它性。悲观锁总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会锁,这样别人再去操作这个数据时就会被阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁,当其他线程想要访问数据时,都需要阻塞挂起。Java 中 synchronized 和 ReentrantLock 等独占锁也是悲观锁思想的实现。悲观锁的特点意味着它适合写操作较多,且并发量较小的场景。

  • 乐观锁:

    乐观锁认为对同一数据的并发操作不会总发生,属于小概率事件,不用每次都对数据上锁。但为保证数据的安全性,还是会在更新的时候会判断一下在此期间别人有没有去更新这个数据,这点不是采用数据库自身的锁机制,而是通过程序来实现。在程序上,我们可以采用版本号机制或者CAS机制实现。Java 中的 java.util.concurrent.atomic 包下的原子变量类就是使用了乐观锁的一种实现方式:CAS 实现的。**乐观锁的特点也意味着它适用于读操作较多的场景,**这样可以提高吞吐量。

小贴士:

乐观锁和悲观锁并不是锁,而是锁的设计思想 。

死锁:

死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,但互不相让,导致双方进入无休止的等待。

产生死锁的必要条件:

  1. 存在两个或者两个以上的事务;
  2. 每个事务都已经持有锁,且在申请另一个锁;
  3. 一个锁资源同时只能被同一个事务持有;
  4. 事务之间因为各自持有双方要的另一个锁,而彼此等待;

死锁的关键在于:两个或以上的事务获取锁的顺序不一样,比如事务 T1 要先获取锁 A 再获取锁 B,而事务 T2 要先获取锁 B 再获取锁 A。如果大家都是先获取锁 A,再获取锁 B,那就不会有死锁问题。

死锁的解决方案:

  1. 方案一:事务直接进入等待,直到超时;

  2. 方案二:发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行;

但由于上述方案都存在一定的局限性,比如方案一可能造成长时间的等待,方案二可能消耗较多 CPU 资源去做死锁检测(比如有 1000 个事务,就要做 1000 * 1000 次检测)。因此还可以考虑下面的方案:

  1. 合理设计索引,使业务 SQL 尽可能通过索引定位更少的行,减少锁竞争;
  2. 调整业务逻辑 SQL 执行顺序,避免 update/delete 长时间持有锁的 SQL在事务前面;
  3. 避免大事务,尽量将大事务拆成多个小事务来处理,通过小事务缩短锁定资源的时间,发生锁冲突的几率也更小;
  4. 在并发比较高的系统中,不要显式加锁,特别是在事务里显式加锁。如 select…for update 语句,在该事务提交前,其他事务需要等待该事务释放锁;
  5. 降低隔离级别。如果业务允许,可以将隔离级别调低,比如从 RR 调为 RC,可以避免掉很多因为 gap 锁造成的死锁;

2.锁的内存结构

在多个未提交事务相继对一条记录做改动时,需要让它们排队执行,这个排队的过程其实是通过锁来实现的。而对一条记录加锁的本质就是在内存中创建一个锁结构与之关联(事务执行时才会创建)。

image-20241225211220272

如上图所示,当一个事务想对一条记录做改动时,首先会看看内存中有没有与这条记录关联的锁结构,当没有的时候就会在内存中生成一个锁结构与之关联。比方说事务 T1 要对这条记录做改动,就需要生成一个锁结构与之关联。为了方便理解,我们对锁的结构进行了简化,仅保留 3 个重要属性:

  • trx 信息:代表这个锁是哪个事务创建的
  • is_waiting:False 代表获取锁成功,True 代表获取锁失败
  • type:代表锁的类型

在上面的例子中,当事务 T1 改动了这条记录后,就生成了一个锁结构与该记录关联,因为之前没有别的事务为这条记录加锁,所以is_waiting 属性就是 false,我们把这个场景就称之为获取锁成功,或者加锁成功,然后就可以继续执行操作了。

对于事务 T2,由于事务 T1 还占用着锁,且锁的类型是 X 锁。因此事务 T2 生成的锁结构中的 is_waiting 属性为 True,代表它需要等待事务 T1 释放锁后才能执行。

3.一致性读与当前读

在 MySQL 中,读操作可以分为快照读(又称一致性读、一致性无锁读)和当前读(又称锁定读)。快照读读取的是记录的可见版本(可能是历史版本),不需要加锁;而当前读读取的是记录的最新版本,并且当前读返回的记录会加上锁(S 锁或 X 锁),以保证其他事务不会再并发修改这条记录‌。

因此,当一条记录加上锁后,其他事务仍然可以进行快照读操作,因为快照读不需要获取锁‌。

参考

  • 《MySQL 是怎样运行的》
  • 《MySQL 45 讲》

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

自然语言处理与知识图谱的融合与应用

目录 前言1. 知识图谱与自然语言处理的关系1.1 知识图谱的定义与特点1.2 自然语言处理的核心任务1.3 二者的互补性 2. NLP在知识图谱构建中的应用2.1 信息抽取2.1.1 实体识别2.1.2 关系抽取2.1.3 属性抽取 2.2 知识融合2.3 知识推理 3. NLP与知识图谱融合的实际应用3.1 智能问答…

模型工作流:自动化的模型内部三角面剔除

1. 关于自动减面 1.1 自动减面的重要性及现状 三维模型是游戏、三维家居设计、数字孪生、VR/AR等几乎所有三维软件的核心资产,模型的质量和性能从根本上决定了三维软件的画面效果和渲染性能。其中,模型减面工作是同时关乎质量和性能这两个要素的重要工…

大语言模型(LLM)中大数据的压缩存储及其重要性

在大型语言模型(LLM)中,KV Cache(键值缓存)的压缩方法及其重要性。 为什么要压缩KV Cache? 计算效率:在生成文本的过程中,每个生成的token都需要与之前所有的token的键值&#xff…

GitLab安装及使用

目录 一、安装 1.创建一个目录用来放rpm包 2.检查防火墙状态 3.安装下载好的rpm包 4.修改配置文件 5.重新加载配置 6.查看版本 7.查看服务器状态 8.重启服务器 9.输网址 二、GitLab的使用 1.创建空白项目 2.配置ssh 首先生成公钥: 查看公钥 把上面的…

从0开始在linux服务器上部署SpringBoot和Vue

目录 一、申请服务器的IP (1)阿里云申请IP (2)设置服务器的密码 (3)远程终端——MobaXterm 二、Docker (1)安装Docker (2)镜像加速 (3&…

企业销售人员培训系统|Java|SSM|VUE| 前后端分离

【技术栈】 1⃣️:架构: B/S、MVC 2⃣️:系统环境:Windowsh/Mac 3⃣️:开发环境:IDEA、JDK1.8、Maven、Mysql5.7 4⃣️:技术栈:Java、Mysql、SSM、Mybatis-Plus、VUE、jquery,html 5⃣️数据库可…

智能家居实训室中,STC单片机驱动的“互联网+”智能家居系统设计

一、引言 随着经济的快速发展,人们对家居环境的智能化、网络化需求日益增强,智能家居的研究也因此受到了国内外相关机构的广泛关注。STC单片机凭借其卓越的性能和广泛的应用领域,成为了智能家居系统设计的优选方案。作为一种先进的微控制器&…

替代传统FTP传输,镭速大数据传输系统实现安全高效数据流转!

信息技术的快速进步让大数据成为了企业决策的关键支撑,但同时也带来了巨大的挑战。企业在运营过程中产生的数据量急剧增加,这对数据传输的速度、安全性和效率提出了更高的要求。然而,传统的FTP传输方式在处理大规模数据时显得力不从心&#x…

渗透Vulnhub-Solidstate靶机

本篇文章旨在为网络安全渗透测试行业靶机教学。通过阅读本文,读者将能够对渗透Vulnhub系列Solidstate靶机有定的了解 一、信息收集阶段 靶机官网:https://www.vulnhub.com/entry/solidstate-1%2C261/ 因为靶机为本地部署虚拟机网段,查看dhcp…

前端下载后端文件流,文件可以下载,但是打不开,显示“文件已损坏”的问题分析与解决方案

目录 场景还原 相关代码开发者工具 - 网络请求记录 问题排查 定位改bug 总结 场景还原 我在前端使用axios接收后端xlsx表格文件流并下载,xlsx文件能够下载成功,但是打开却显示文件无法打开 相关代码 请求API封装:Content–Type以及responseType经核…

什么样的LabVIEW控制算自动控制?

自动控制是指系统通过预先设计的算法和逻辑,在无人工干预的情况下对被控对象的状态进行实时监测、决策和调整,达到预期目标的过程。LabVIEW作为一种图形化编程工具,非常适合开发自动控制系统。那么,什么样的LabVIEW控制算作“自动…

【机器学习】探索机器学习与人工智能:驱动未来创新的关键技术

探索机器学习与人工智能:驱动未来创新的关键技术 前言:人工智能的核心技术深度学习:自然语言处理(NLP):计算机视觉: 机器学习与人工智能的驱动创新医疗健康领域金融行业智能制造与工业互联网智慧…

在 Vue3 项目中实现计时器组件的使用(Vite+Vue3+Node+npm+Element-plus,附测试代码)

一、概述 记录时间 [2024-12-26] 本文讲述如何在 Vue3 项目中使用计时器组件。具体包括开发环境的配置,ViteVue 项目的创建,Element Plus 插件的使用,以及计时器组件的创建和使用。 想要直接实现计时器组件,查看文章的第四部分。…

图神经网络_图嵌入_Struc2Vec

0 背景 之前的node embedding方式,都是基于近邻关系,但是有些节点没有近邻,也有结构相似性。如图中的u、v节点。 struc2vec算法适用于捕获结构相似性。 1 相似度(距离)计算 1.1 公式 f k ( u , v ) f k − 1 ( u …

JZ31 栈的压入、弹出序列

题目来源:栈的压入、弹出序列_牛客题霸_牛客网 题目:如下 输入两个整数序列,第一个序列表示栈的压入顺序,请判断第二个序列是否可能为该栈的弹出顺序。假设压入栈的所有数字均不相等。例如序列1,2,3,4,5是某栈的压入顺序&#xf…

Android 蓝牙开发-传输数据

概述 传统蓝牙是通过建立REFCCOM sockect来进行通信的,类似于socket通信,一台设备需要开放服务器套接字并处于listen状态,而另一台设备使用服务器的MAC地址发起连接。连接建立后,服务器和客户端就都通过对BluetoothSocket进行读写…

Java圣诞树

目录 写在前面 技术需求 程序设计 代码分析 一、代码结构与主要功能概述 二、代码功能分解与分析 1. 类与常量定义 2. 绘制树的主逻辑 3. 彩色球的绘制 4. 动态效果的实现 5. 窗口初始化 三、关键特性与优点 四、总结 写在后面 写在前面 Java语言绘制精美圣诞树…

认识计算机网络

单单看这一个词语,有熟悉又陌生,让我们来重新认识一下这位大角色——计算机网络。 一、是什么 以及 怎么来的 计算机网络是指将地理位置不同的具有独立功能的多台计算机及其外部设备,通过通信线路和通信设备连接起来,在网络操作…

【再谈设计模式】享元模式~对象共享的优化妙手

一、引言 在软件开发过程中,我们常常面临着创建大量细粒度对象的情况,这可能会导致内存占用过高、性能下降等问题。享元模式(Flyweight Pattern)就像是一位空间管理大师,它能够在不影响功能的前提下,有效地…

用Python写炸金花游戏

文章目录 **代码分解与讲解**1. **扑克牌的生成与洗牌**2. **给玩家发牌**3. **打印玩家的手牌**4. **定义牌的优先级**5. **判断牌型**6. **确定牌型优先级**7. **比较两手牌的大小**8. **打印结果** 完整代码 以下游戏规则: 那么我们要实现的功能,就是…