MySQL中的锁与MVCC

目录

共享锁(Shared Locks)

排他锁(Exclusive Locks)

意向锁(Intention Locks)

记录锁(Record Locks)

临键锁(Next-Key Locks)

MVCC机制

MVCC的核心概念

MVCC在InnoDB中的实现

MVCC的工作原理

MVCC的优势与局限

隔离机制

读未提交(Read Uncommitted)

读已提交(Read Committed)

可重复读(Repeated Read)

可串行化(Serializable)


在MySQL的InnoDB存储引擎中,锁是用于管理并发访问的一种机制。InnoDB支持多种锁类型,每种锁都有其特定的机制和应用场景。以下是MySQL InnoDB中五种常见的锁及其各自机制的详细介绍:

共享锁(Shared Locks)

  • 定义:共享锁又称为读锁,允许多个事务同时读取同一数据,但不允许修改。
  • 机制:当一个事务对某行数据加上共享锁后,其他事务仍然可以读取该行数据,但不能修改或删除。共享锁在事务结束时自动释放。
  • 使用场景:适用于需要并发读取数据的场景,如读取频繁且不需要修改的数据。

排他锁(Exclusive Locks)

  • 定义:排他锁又称为写锁,不允许其他事务读取或修改被锁定的数据。
  • 机制:当一个事务对某行数据加上排他锁后,其他事务无法读取或修改该行数据,直到锁被释放。排他锁在事务结束时自动释放。
  • 使用场景:适用于需要修改数据的场景,如更新、删除操作。

意向锁(Intention Locks)

  • 定义:意向锁是InnoDB在加行锁之前自动添加的表级锁,用于表示事务即将对表中的某些行加锁。
  • 机制:意向锁分为意向共享锁(IS)和意向排他锁(IX)。意向共享锁表示事务准备给数据行加入共享锁,意向排他锁表示事务准备给数据行加入排他锁。意向锁之间以及意向锁与行锁之间互不冲突,但意向锁的存在可以阻止其他事务对表加锁。
  • 使用场景:意向锁是InnoDB内部使用的锁,不需要用户显式添加。它们提高了加锁的效率,避免了在加行锁时需要对整个表进行扫描。

记录锁(Record Locks)

  • 定义:记录锁是InnoDB在唯一索引或主键索引上加的锁,用于锁定具体的索引项。
  • 机制:当一个事务对某行数据加上记录锁后,其他事务无法修改或删除该行数据,但可以读取(取决于隔离级别)。记录锁在事务结束时自动释放。
  • 使用场景:适用于对唯一索引或主键索引进行等值查询并需要加锁的场景。

临键锁(Next-Key Locks)

  • 定义:临键锁是InnoDB在范围查询时加的锁,它结合了记录锁和间隙锁的功能。
  • 机制:临键锁不仅锁定查询范围内的索引项,还锁定这些索引项之间的间隙。这可以防止其他事务在查询范围内插入新的数据行,从而解决幻读问题。临键锁在事务结束时自动释放。
  • 使用场景:适用于需要防止幻读的场景,如范围查询。

另外,虽然不属于上述五种锁之一,但间隙锁(Gap Locks)也是InnoDB中一种重要的锁类型。间隙锁用于锁定索引项之间的间隙,防止其他事务在这些间隙中插入新的数据行。它通常与临键锁一起使用,以提供更强大的并发控制。

MVCC机制

MVCC,全称Multi-Version Concurrency Control,即多版本并发控制,是一种用于管理并发访问数据库的机制。以下是对MVCC机制的详细解释:

MVCC的核心概念

MVCC的核心思想是通过维护数据的多个版本来实现并发控制。在每次更新数据时,数据库不会直接覆盖旧的数据,而是会生成一个新版本的记录。这样,每个事务都可以看到一个与其隔离级别相符合的数据快照。

MVCC在InnoDB中的实现

在MySQL的InnoDB存储引擎中,MVCC主要通过以下方式实现:

  1. 隐藏列:InnoDB为每行数据都添加了两个隐藏列,分别是trx_idroll_pointertrx_id记录了最后一次修改该行的事务ID,而roll_pointer则指向了存储旧版本的Undo Log(回滚日志)的指针。
  2. Undo Log:Undo Log是MVCC机制的核心组件,它负责存储数据的历史版本。每当事务修改数据时,InnoDB都会将数据的旧版本写入Undo Log,并通过roll_pointer与新版本关联起来,形成一个链表结构。这个链表结构就是所谓的“版本链”。
  3. ReadView:在事务执行快照读时,InnoDB会生成一个一致性视图(ReadView)。这个视图反映了事务开始时刻数据库的快照,并用于判断哪些数据版本对当前事务可见。

MVCC的工作原理

  1. 快照读:在MVCC机制下,普通的SELECT查询操作是快照读。这意味着查询操作会读取一个一致性视图中的数据,而不是直接读取最新的数据版本。这样,即使有其他事务在并发地修改数据,快照读也能保证读取到一致的数据。
  2. 当前读:与快照读不同,当前读总是读取最新版本的数据,并且会对读取的记录进行加锁。MySQL中的SELECT ... LOCK IN SHARE MODE和SELECT ... FOR UPDATE等操作都是当前读。
  3. 数据可见性判断:在事务执行快照读时,InnoDB会根据ReadView和版本链来判断哪些数据版本对当前事务可见。具体来说,如果某个数据版本的trx_id小于当前事务的ID,并且该版本在ReadView创建时已经提交,则这个数据版本对当前事务可见。

MVCC的优势与局限

  1. 优势

    • 提高并发性能:通过快照读,多个事务可以并发执行读操作而不需要加锁,从而减少了读写锁竞争,提高了并发性能。
    • 避免锁等待:由于读操作不需要加锁,因此减少了读写事务之间的锁等待时间,提高了系统吞吐量。
    • 一致性保证:在较高的事务隔离级别(如可重复读)下,MVCC保证了读到的数据的一致性,同时不会牺牲并发性。
  2. 局限

    • 存储开销:由于需要存储多个版本的数据以及回滚日志,可能会导致存储空间的浪费。特别是在长时间运行的事务中,旧版本数据占用的空间会越来越大。
    • 回滚日志管理:回滚日志的生成和清理会增加系统负担,影响数据库的性能。特别是在长事务下,回滚日志可能会变得很大,影响系统的正常运行。
    • 长事务影响:如果一个事务持续时间过长,它持有的快照和Undo Log会阻止系统清理旧数据版本,导致数据库性能下降。

隔离机制

MySQL通过不同的机制实现了读未提交(Read Uncommitted)、读已提交(Read Committed)、可重复读(Repeated Read)和可串行化(Serializable)这几种隔离级别。以下是每种隔离级别的实现方式的详细解释:

读未提交(Read Uncommitted)

  • 实现方式:在读未提交隔离级别下,所有的读操作都不加锁,因此可以读取到最新的数据,包括其他事务未提交的数据。写操作会加行级锁,写完即释放。
  • 特点:可能读取到其他会话中未提交事务修改的数据,即允许脏读。此隔离级别的性能较好,但数据一致性较差。
  • 技术:使用MVCC(多版本并发控制)技术,但在此级别下,MVCC的优势并不明显,因为读操作不依赖于数据的版本链。

读已提交(Read Committed)

  • 实现方式:在读已提交隔离级别下,一个事务只能读取到已经提交事务所做的更改。未提交事务的更改对当前事务是不可见的。MySQL通过MVCC来实现这一隔离级别。

  • 特点:避免了脏读,但可能出现不可重复读,即在一个事务的两次查询中,数据可能不一致。

  • 技术

    • MVCC:为每行数据保存多个版本,每个版本包含数据的快照以及事务的元信息(如创建该版本的事务ID)。当事务执行读操作时,会检查数据行的事务ID和当前事务的视图(即当前事务开始时哪些事务已经提交)。如果数据行的事务ID小于当前事务视图中的最小已提交事务ID,则该行对当前事务是可见的;否则,该行对当前事务是不可见的,InnoDB会查找该行的上一个版本(如果存在)。
    • Read View:为每个事务创建一个一致性快照,包含了事务开始时所有已提交的数据版本以及事务自己所做的修改。

可重复读(Repeated Read)

  • 实现方式:在可重复读隔离级别下,同一个事务内的查询都是事务开始时刻一致的。这通过MVCC和事务开始时创建的Read View来实现。

  • 特点:避免了脏读和不可重复读,但还存在幻读的可能性(即在一个事务的两次查询中数据笔数不一致)。在MySQL的InnoDB存储引擎中,可重复读是默认的隔离级别。

  • 技术

    • MVCC和Read View:与读已提交隔离级别类似,但Read View是在事务开始时创建的,而不是在执行每个语句时创建。这确保了同一个事务内的多次查询结果是一致的。
    • 间隙锁(Gap Locks):在可重复读隔离级别下,InnoDB还会使用间隙锁来防止幻读。间隙锁锁定的是数据行之间的“间隙”,而不是具体的数据行本身。这可以防止其他事务在已锁定的间隙中插入新行,从而维护数据的一致性。

可串行化(Serializable)

  • 实现方式:可串行化是最高的隔离级别,它通过强制事务排序来避免冲突。在MySQL中,可以通过两种方式实现可串行化:基于锁的实现和基于MVCC的实现。

  • 特点:完全避免了脏读、不可重复读和幻读。但可能导致大量的超时现象和锁竞争,降低并发性能。

  • 技术

    • 基于锁的实现:当一个事务需要对某个数据进行修改时,系统会为该数据加上排它锁,其他事务在此时无法对该数据进行修改或查询,直到当前事务释放锁为止。
    • 基于MVCC的实现:为每个事务创建一个唯一的版本号,并当事务需要对数据进行修改时,系统会为该数据创建一个新的版本,并将当前事务的版本号与数据进行关联。其他事务在此时只能看到该数据之前的版本,而无法看到当前事务修改后的版本。

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

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

相关文章

电子应用设计方案-30:智能扫地机器人系统方案设计

智能扫地机器人系统方案设计 一、引言 随着人们生活节奏的加快和对生活品质的追求,智能家居产品越来越受到消费者的青睐。智能扫地机器人作为一种能够自动清扫地面的智能设备,为人们节省了大量的时间和精力。本方案旨在设计一款功能强大、智能化程度高、…

从简单的自动化脚本到复杂的智能助手:Agent技术的实践与应用

现代软件开发中,Agent技术正在悄然改变着我们构建应用程序的方式。一个Agent就像是一个能独立完成特定任务的智能助手,它可以感知环境、作出决策并采取行动。让我们通过实际案例,深入了解如何运用Agent技术来构建智能系统。 想象你正在开发一…

Ubuntu Server 22.04.5 从零到一:详尽安装部署指南

文章目录 Ubuntu Server 22.04.5 从零到一:详尽安装部署指南一、部署环境二、安装系统2.1 安装2.1.1 选择安装方式2.1.2 选择语言2.1.3 选择不更新2.1.4 选择键盘标准2.1.5 选择安装版本2.1.6 设置网卡2.1.7 配置代理2.1.8 设置镜像源2.1.9 选择装系统的硬盘2.1.10 …

定时/延时任务-ScheduledThreadPoolExecutor的使用

文章目录 1. 概要2. 固定速率和固定延时2.1 固定速率2.2 固定延时 3. API 解释3.1 schedule3.2 固定延时 - scheduleWithFixedDelay3.2 固定速率 - scheduleWithFixedDelay 4. 小结 1. 概要 前三篇文章的地址: 定时/延时任务-自己实现一个简单的定时器定时/延时任…

Linux操作系统学习---初识环境变量

目录 ​编辑 环境变量的概念: 小插曲:main函数的第一、二个参数 获取环境变量信息: 1.main函数的第三个参数 2.查看单个环境变量 3.c语言库函数getenv() 和环境变量相关的操作指令: 1.export---导出环境变量: 2.unse…

husky,commit规范,生成CHANGELOG.md,npm发版

项目git提交工程化(钩子,提交信息commit message),npm修改版本,需要涉及到的包: husky,允许在git钩子中执行不同的脚步,如commitlint,eslint,prettier&#…

基于Python的飞机大战复现

✨✨ 欢迎大家来访Srlua的博文(づ ̄3 ̄)づ╭❤~✨✨ 🌟🌟 欢迎各位亲爱的读者,感谢你们抽出宝贵的时间来阅读我的文章。 我是Srlua小谢,在这里我会分享我的知识和经验。&am…

【趣味】斗破苍穹修炼文字游戏HTML,CSS,JS

目录 图片展示 游戏功能 扩展功能 完整代码 实现一个简单的斗破苍穹修炼文字游戏,你可以使用HTML、CSS和JavaScript结合来构建游戏的界面和逻辑。以下是一个简化版的游戏框架示例,其中包含玩家修炼的过程、增加修炼进度和显示经验值的基本功能。 图片…

005 MATLAB符号微积分

前言: 在MATLAB中,数值与符号的主要区别在于它们的处理方式和应用场景 数值计算适用于实际的数值计算问题,如矩阵运算、数据分析等。符号计算适用于符号推导、公式化简和符号解析,如理论物理和工程计算。 01 符号对象 1.基本符…

Android 13 编译Android Studio版本的Launcher3

Android 13 Aosp源码 源码版本Android Studio版本Launcher3QuickStepLib (主要代码) Launcher3ResLib(主要资源)Launcher3IconLoaderLib(图

Ubuntu交叉编译 opencv for QNX

前言 在高通板子上开发一些程序的时候,会用到opencv帮助处理一下图像数据,高通车载板子sa8155和sm8295都有QNX os,需要交叉编译opencv的库,(这个交叉编译真是搞得我太恶心了,所以进行一个记录和分享) 搜了很多资料,有些太过于复杂,有些也存在错误导致最后没有编译成…

NVR监测软件EasyNVR多个NVR同时管理:录播主机的5条常见问题与解决办法

视频监控广泛应用于城市治安、交通管理、商业安保及家庭监控等领域。在使用EasyNVR平台管理多个NVR设备时,尤其是涉及到海康录播主机的场景中,使用者可能会遇到一些常见问题。本文将探讨海康录播主机的五个常见问题及其解决办法。 1、海康录播主机的5条常…

力扣刷题TOP101:6.BM7 链表中环的入口结点

目录: 目的 思路 复杂度 记忆秘诀 python代码 目的 {1,2},{3,4,5}, 3 是环入口。 思路 这个任务是找到带环链表的环入口。可以看作是上一题龟兔赛跑(Floyd 判圈算法)的延续版:乌龟愤愤不平地举报兔子跑得太快,偷偷…

网关: 用途和产品对比

概述 微服务中的有一个非常关键的组件: API网关 和配置中心一样,在没有采用微服务架构的时候 我们可以自己搭建自己的API网作作为统一的 API 出口和安全验证 在微服务架构之下,服务被拆的非常的零散,在降低了耦合度的同时 也给服务的统一…

Java ConcurrentHashMap

Java Map本质不是线程安全的,HashTable和Collections同步包装器(Synchronized Wrapper)在并发场景下性能低。Java还为实现 Map 的线程安全提供了并发包,保证线程安全的方式从synchronize简单方式到精细化,比如Concurre…

Spring 自调用事务失效分析及解决办法

前言 博主在写公司需求的时候,有一个操作涉及到多次对数据库数据的修改。当时就想着要加 Transactional注解来声名事务。并且由于一个方法中有太多行了,于是就想着修改数据库的操作单独提取出来抽象成一个方法。但这个时候,IDEA 提示我自调用…

【LeetCode每日一题】——189.轮转数组

文章目录 一【题目类别】二【题目难度】三【题目编号】四【题目描述】五【题目示例】六【题目提示】七【题目进阶】八【解题思路】九【时空频度】十【代码实现】十一【提交结果】 一【题目类别】 数组 二【题目难度】 中等 三【题目编号】 189.轮转数组 四【题目描述】 …

Spark基本命令详解

文章目录 Spark基本命令详解一、引言二、Spark Core 基本命令1、Transformations(转换操作)1.1、groupBy(func)1.2、filter(func) 2、Actions(动作操作)2.1、distinct([numTasks])2.2、sortBy(func, [ascending], [numTasks]) 三、…

AppFlow:支持飞书机器人调用百炼应用

AppFlow:支持飞书机器人调用百炼应用 简介: 本文介绍了如何创建并配置飞书应用及机器人,包括登录飞书开发者后台创建应用、添加应用能力和API权限,以及通过AppFlow连接流集成阿里云百炼服务,最后详细说明了如何将机器…

基于vite创建一个脚手架(快速入门)

Vite是一种新型的前端构建工具,主要用于构建现代化的Web应用程序。以 原生ESM 方式提供源码。这实际上是让浏览器接管了打包程序的部分工作:Vite 只需要在浏览器请求源码时进行转换并按需提供源码。根据情景动态导入代码,即只在当前屏幕上实际…