MySQL中的锁与MVCC

server/2024/12/5 17:23:34/

目录

共享锁(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的实现:为每个事务创建一个唯一的版本号,并当事务需要对数据进行修改时,系统会为该数据创建一个新的版本,并将当前事务的版本号与数据进行关联。其他事务在此时只能看到该数据之前的版本,而无法看到当前事务修改后的版本。

http://www.ppmy.cn/server/146258.html

相关文章

【线上问题记录 | 排查网络连接问题】

问题描述 现在有我们程序是部署在服务器A的,A链接的是B。程序从B的redis进行存储和取数据的。 我们的业务是: 信息展示,也就是如果发现机器有异常了,实时进行监控。突然发现有一天,信息显示延迟了。 然后我们就开始排查究竟什么原…

在xml的sql的子查询中使用row_number over之后再在mapper的接口层传入Page对象实现分页功能,出现Bug

1.报错信息复现&#xff1a; Mapper接口&#xff1a; List<UserInfo> queryUserPage(Param(“vo”) UserQury query,Page<UserInfo> page); UserQury 类中的状态字段&#xff1a; ApiModelproperty(“状态”) private String status; Xml中sql如下&#xff1…

详解SpringCloud集成Camunda7.19实现工作流审批(二)

本章将分享的是camunda流程设计器--Camunda Modeler的基本使用&#xff08;对应camunda版本是7.19&#xff09;&#xff0c;包括bpmn流程图画法&#xff0c;各种控件使用以及一些日常业务场景的流程图的实现 参考资料&#xff1a; Camunda BPMN 基础组件-CSDN博客 Camunda: Exe…

【PX4_Autopolite飞控源码】中飞控板初始化过程中的引脚IO控制(拉低/拉高)

先选择自己飞控板支持的硬件平台 打开对应的路径我的是Desktop/px4/PX4-Autopilot/boards/zhty/nora 找到board_config.h文件&#xff0c;打开nora后再往下去找Desktop/px4/PX4-Autopilot/boards/zhty/nora/src/borad_config.h 打开后可以看到有很多GPIO引脚的定义&#xff0c…

UPLOAD LABS | PASS 01 - 绕过前端 JS 限制

关注这个靶场的其它相关笔记&#xff1a;UPLOAD LABS —— 靶场笔记合集-CSDN博客 0x01&#xff1a;过关流程 本关的目标是上传一个 WebShell 到目标服务器上&#xff0c;并成功访问&#xff1a; 我们直接尝试上传后缀为 .php 的一句话木马&#xff1a; 如上&#xff0c;靶场弹…

鲜花销售管理系统|Java|SSM|VUE| 前后端分离

【重要1⃣️】前后端源码万字文档部署文档 【重要2⃣️】正版源码有问题包售后 【重要3⃣️】可复制品不支持退换货 【包含内容】 【一】项目提供非常完整的源码注释 【二】相关技术栈文档 【三】源码讲解视频 【其它服务】 【一】可…

Day48 | 动态规划 :线性DP 编辑距离

Day48 | 动态规划 &#xff1a;线性DP 编辑距离 动态规划应该如何学习&#xff1f;-CSDN博客 本次题解参考自灵神的做法&#xff0c;大家也多多支持灵神的题解 最长公共子序列 编辑距离_哔哩哔哩_bilibili 动态规划学习&#xff1a; 1.思考回溯法&#xff08;深度优先遍历…

【青牛科技】电动工具电流反馈型相位控制电路D2010

概述&#xff1a; D2010是一块相位控制集成电路&#xff0c;采用双级工艺。具有负载电流保护、软启动等功能。广泛应用于机床马达的控制。 主要特点: 全波电流感应 主电源可调软启动 防止过流及过高输出程控电流大小&#xff0c; 电压与电流同步 自动触发开关内部电压监控申流…