Mysql组合索引的update在多种情况下的间隙锁的范围(简单来说)

简单来说,当 UPDATE 语句的 WHERE 条件使用了组合索引,并且需要锁定不存在的“间隙”来防止幻读时,就会产生间隙锁。间隙锁的范围取决于 WHERE 条件如何利用组合索引,以及数据库的隔离级别。

我们用图书馆的例子。比如:

  • 分类(Category):计算机、历史、文学
  • 出版年份(PublishYear):2020、2021、2022
  • 书名(Title):具体书名

现在,图书馆对 (Category, PublishYear, Title) 建立了一个组合索引。这意味着书架上的书是先按分类排好,然后在每个分类里再按出版年份排好,最后在每个年份里按书名排好。

假设你现在是图书馆管理员,要进行一些更新操作。

核心问题: 当你更新某些书时,为了防止别人在你更新期间偷偷“插入”或“删除”一些书,导致你更新完后发现书的数量不对(幻读),你需要锁定一些“空位”(间隙)。这些空位锁定的范围有多大?

深入理解:

间隙锁是 InnoDB 存储引擎在 可重复读(Repeatable Read) 隔离级别下,为了解决 幻读(Phantom Read) 问题而引入的一种锁。它锁定的是索引记录之间的“间隙”,或者索引记录之前/之后的空间。

UPDATE 语句使用组合索引时,间隙锁的范围会变得比较复杂,因为它涉及到索引的“最左前缀原则”以及 WHERE 条件的匹配程度。

我们分几种情况来讨论:

情况一:WHERE 条件完全匹配组合索引的“最左前缀”或全部列,且是等值查询。

场景: 你想更新“计算机”分类下,“2021年”出版的,名为“数据库原理”这本书的价格。
UPDATE books SET price = 100 WHERE category = '计算机' AND publish_year = 2021 AND title = '数据库原理';

索引: (Category, PublishYear, Title)

  1. 数据库会通过组合索引精确找到这本书。
  2. 由于是精确匹配,并且找到了具体的记录,数据库会给这条记录加上行级排他锁(X Lock)
  3. 间隙锁: 在这种情况下,如果 WHERE 条件能够精确匹配到一条或几条存在的记录,并且这些记录是连续的,那么间隙锁的范围通常会非常小,甚至可能没有明显的间隙锁(因为行锁已经足够)。
    • 为什么? 因为你已经找到了具体的书,你只需要锁住这本书本身。如果其他人在这个位置插入一本完全相同的书(这通常被唯一索引阻止),或者插入一本在排序上紧邻的书,并不会影响你当前对“数据库原理”这本书的更新。
    • 例外: 如果 WHERE 条件匹配到了一个不存在的记录,但这个记录可能存在于某个间隙中(例如,你尝试更新一本不存在的书),那么为了防止幻读,可能会在这个不存在的记录应该插入的位置前后加上间隙锁。但对于精确匹配存在的记录,间隙锁通常不是主要考虑。
情况二:WHERE 条件只使用了组合索引的部分列(最左前缀),且是等值查询。

场景: 你想更新“计算机”分类下,所有“2021年”出版的书的价格。
UPDATE books SET price = 100 WHERE category = '计算机' AND publish_year = 2021;

索引: (Category, PublishYear, Title)

  1. 数据库会通过组合索引找到所有 category = '计算机'publish_year = 2021 的书。
  2. 它会给这些找到的所有行都加上行级排他锁(X Lock)
  3. 间隙锁: 这是间隙锁发挥作用的关键场景。为了防止其他事务在“计算机”分类下,“2021年”出版的书籍之间或前后插入新的书籍(例如,插入一本 title = '操作系统' 的书),数据库会在这些行之间以及这些行所在的“范围”前后加上间隙锁。
    • 范围: 间隙锁会锁定 (Category='计算机', PublishYear=2021) 这个“范围”内的所有可能的 Title 值。
    • 具体表现: 假设在索引中,('计算机', 2021, '算法') 后面是 ('计算机', 2021, '数据结构')。那么,('计算机', 2021, '算法')('计算机', 2021, '数据结构') 之间的间隙会被锁定。同时,('计算机', 2021, '数据结构') 之后,直到下一个 ('计算机', 2022, ...)('历史', ...) 之前的间隙也会被锁定。
    • 目的: 确保在你更新期间,没有人能插入新的 ('计算机', 2021, ...) 的书,从而避免幻读。
情况三:WHERE 条件使用了范围查询(BETWEEN, >, <, LIKE 等)。

场景: 你想更新“计算机”分类下,所有“2020年到2022年”出版的书的价格。
UPDATE books SET price = 100 WHERE category = '计算机' AND publish_year BETWEEN 2020 AND 2022;

索引: (Category, PublishYear, Title)

  1. 数据库会通过组合索引找到所有 category = '计算机'publish_year 在 2020 到 2022 之间的书。
  2. 它会给这些找到的所有行都加上行级排他锁(X Lock)
  3. 间隙锁: 间隙锁的范围会覆盖整个查询的范围。
    • 起始点: 间隙锁会从 ('计算机', 2020, MIN_VALUE) 之前的间隙开始。
    • 结束点: 间隙锁会延伸到 ('计算机', 2022, MAX_VALUE) 之后的间隙。
    • 中间:('计算机', 2020, ...)('计算机', 2022, ...) 之间的所有行和间隙都会被锁定。这意味着,即使 ('计算机', 2021, '操作系统') 这本书不存在,它应该存在的位置也会被间隙锁覆盖,防止其他事务插入。
    • 目的: 确保在你更新这个范围内的书时,没有人能插入或删除任何符合这个范围的新书,从而避免幻读。
情况四:WHERE 条件没有使用组合索引的最左前缀,或者没有使用索引。

场景: 你想更新所有“2021年”出版的书的价格(不考虑分类)。
UPDATE books SET price = 100 WHERE publish_year = 2021;

索引: (Category, PublishYear, Title)

  1. 由于 WHERE 条件没有使用组合索引的最左前缀(Category),数据库可能无法有效利用这个组合索引。
  2. 全表扫描: 数据库可能会进行全表扫描来找到所有 publish_year = 2021 的行。
  3. 锁的升级: 在这种情况下,为了保证事务的隔离性,数据库可能会采取更粗粒度的锁策略:
    • 表级锁: 最坏的情况是,数据库为了避免幻读,直接对整个 books 表加表级排他锁(Table-Level X Lock)。这意味着在你的 UPDATE 语句执行期间,其他任何对 books 表的读写操作都会被阻塞。
    • 行锁 + 间隙锁(但范围可能很大): 即使是行锁,由于是全表扫描,它会扫描所有行,并对符合条件的行加行锁。同时,为了防止幻读,它可能需要在整个扫描过程中,对所有扫描到的间隙都加上间隙锁。这实际上等同于锁定了整个表,因为间隙锁会覆盖所有可能的插入点。
    • 目的: 确保在全表扫描并更新的过程中,没有新的行被插入或删除,从而避免幻读。
情况五:WHERE 条件使用了组合索引,但条件不精确,导致索引扫描范围很大。

场景: 你想更新所有 category 以“C”开头的书的价格。
UPDATE books SET price = 100 WHERE category LIKE 'C%';

索引: (Category, PublishYear, Title)

  1. 数据库会利用 Category 上的索引(最左前缀)来查找。
  2. 它会扫描所有 Category 以 ‘C’ 开头的索引项。
  3. 间隙锁: 间隙锁的范围会覆盖所有 Category 以 ‘C’ 开头的索引项以及它们之间的所有间隙。
    • 具体表现: 假设你的索引中有 ('计算机', ...)('财务', ...) 等。那么从第一个以 ‘C’ 开头的 Category 之前,到最后一个以 ‘C’ 开头的 Category 之后,所有相关的间隙都会被锁定。
    • 目的: 防止其他事务插入新的 Category 以 ‘C’ 开头的书籍,从而避免幻读。

总结间隙锁的范围:

间隙锁的范围是动态的,它取决于:

  1. 隔离级别: 间隙锁主要在 可重复读(Repeatable Read) 隔离级别下生效。在读已提交(Read Committed)隔离级别下,通常不会有间隙锁(除非是外键约束检查等特殊情况)。
  2. WHERE 条件如何利用索引:
    • 精确匹配(等值查询)到存在记录: 间隙锁范围最小,通常只锁定行本身。
    • 范围查询(BETWEEN, >, <, LIKE 等)或部分索引列匹配: 间隙锁会锁定整个查询范围内的所有行和间隙,以防止幻读。范围越大,间隙锁的范围也越大。
    • 无法使用索引或索引效率低下: 可能导致全表扫描,进而可能升级为表级锁,或者间隙锁覆盖整个表,导致并发性急剧下降。
  3. 索引的类型:
    • 唯一索引: 如果 WHERE 条件通过唯一索引精确匹配到一条记录,通常只需要行锁,间隙锁的影响很小。
    • 非唯一索引: 非唯一索引更容易产生间隙锁,因为存在多个相同值的可能性,以及在这些相同值之间插入新值的可能性。

核心思想: 间隙锁是为了保护一个“范围”内的“不存在”的数据,防止其他事务在这个范围内插入新的数据,从而破坏当前事务的“可重复读”的幻象。UPDATE 操作在定位到要修改的行后,为了确保这些行在事务提交前不会被其他事务的插入操作所“包围”或“改变其相对位置”,就会对相关的间隙加锁。

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

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

相关文章

什么是Apache Ignite的affinity(亲和性)

在 Apache Ignite 中&#xff0c; affinity&#xff08;亲和性&#xff09; 是一种用于控制数据分布和查询性能的重要机制。它允许开发者指定数据如何在集群中的节点之间分布&#xff0c;从而优化数据访问和查询效率。以下是关于 affinity 的详细解释&#xff1a;数据亲和性&a…

youtube图论

dfs排序lifo & fifo存储方式邻接矩阵dijstra处理过的保存/更新&#xff0c;意味着一个节点避免了重复访问bfs dfs

借助ssh实现web服务的安全验证

背景 公有云服务器 http 服务 80端口&#xff0c;想做到安全访问无须HTTPS 客户端证书方便、快捷、安全 SSH 隧道 本地代理 使用 SSH 隧道将 HTTP 服务“隐藏”在 SSH 之后&#xff1a; # 客户端建立隧道&#xff08;将本地 8080 转发到服务器的 80 端口&#xff09; ssh…

状态机在前端开发中的艺术:从理论到框架级实践

文章目录一 状态机&#xff1a;复杂逻辑的终结者1.1 什么是状态机&#xff1f;1.2 为何前端需要状态机&#xff1f;二 状态机核心概念深度解析2.1 有限状态机&#xff08;FSM&#xff09;与分层状态机&#xff08;HSM&#xff09;2.2 状态机的数学表示三 前端开发中的状态机实战…

把word中表格转成excle文件

把word中表格转成excle文件 from docx import Document from openpyxl import Workbook from pathlib import Path# 打开 Word 文档 document Document(./weather_report.docx) tables document.tables# 输出文件路径 output_file Path(./weather_report.xlsx)# 如果文件已存…

运维打铁: 阿里云 ECS 实例的高效运维与管理

文章目录思维导图正文内容一、实例基础管理1. 实例创建2. 实例配置调整3. 实例停止与启动二、性能监控与优化1. 系统性能指标监控2. 磁盘 I/O 优化3. 网络优化三、安全防护1. 防火墙设置2. 账号安全管理3. 数据备份与恢复四、自动化运维1. 脚本自动化2. 使用云助手五、成本优化…

RV1126平台(Buildroot Linux)+ SunplusIT SPCA2688 USB摄像头 RTSP推流全流程复盘与问题解决记录

# RK RV1126平台&#xff08;Buildroot Linux&#xff09; SunplusIT SPCA2688 USB摄像头 RTSP推流全流程复盘与问题解决记录一、平台与需求- **硬件平台**&#xff1a;Rockchip RV1126 - **操作系统**&#xff1a;基于Buildroot定制的Linux系统 - **USB摄像头**&#xff1a;Su…

深入理解Java虚拟机:Java内存区域与内存溢出异常

前言Java虚拟机&#xff08;JVM&#xff09;的自动内存管理是其核心特性之一&#xff0c;它极大地简化了开发者的工作&#xff0c;减少了内存泄漏和内存溢出的问题。本文将详细介绍JVM的自动内存管理机制的内存区域与内存溢出异常问题&#xff0c;包括运行时数据区域、对象的创…

位图入门算法191. 位1的个数

题目链接&#xff1a; 191. 位1的个数 - 力扣&#xff08;LeetCode&#xff09; 这道题让我们找出一个数字中二进制中1的个数&#xff0c;这个题目我们就用1的&来解决&#xff0c;最后一位有0为0&#xff0c;都是1才是1&#xff0c;我们只需要判断32次即可。 代码如下&am…

[架构之美]虚拟机Ubuntu密码重置

[架构之美]虚拟机Ubuntu密码重置 当您在虚拟机中运行Ubuntu系统时&#xff0c;忘记密码不再意味着数据丢失&#xff01;本文将详细介绍可靠的密码重置方法&#xff0c;帮助您快速恢复系统访问权限。 一、虚拟机密码重置原理与准备 1.1 为什么虚拟机重置密码更容易 在虚拟机环…

kotlin中withContext,async,launch几种异步的区别

在 Kotlin 协程中&#xff0c;withContext、async 和 launch 是常用的异步/并发操作函数&#xff0c;它们的主要区别在于用途和返回值&#xff1a;1. launch 作用&#xff1a;启动一个新的协程&#xff0c;用于执行不返回结果的并发任务。使用场景&#xff1a;适合执行没有返回…

git 报错fatal: refusing to merge unrelated histories

解决方案在你操作命令后面加--allow-unrelated-histories 例如&#xff1a; git merge master --allow-unrelated-historiesgit pull或者git push报fatal: refusing to merge unrelated histories 同理&#xff1a; git pull origin master --allow-unrelated-histories

Android 13----在framworks层映射一个物理按键

基于Android 13.一、映射步骤确定要映射的物理按键值在kl文件中增加键值对在InputEventLabels.cpp增加AKEYCODE在keycodes.h中定义AKEYCODE值attrs.xml中增加KEYCODEKeyEvent.java中增加KEYCODE在PhoneManagerWindow等相关类中进行拦截处理相关KEYCODE&#xff0c;属于具体的业…

【Java EE】Mybatis-Plus

1. 开始先进行和以前一样的项目配置、数据库连接配置&#xff0c;在这些基础上&#xff0c;额外引入 Mybatis-Plus 依赖即可。<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-spring-boot3-starter</artifactId><vers…

各版本操作系统对.NET支持情况(250707更新)

借助虚拟机和测试机&#xff0c;检测各版本操作系统对.NET的支持情况。 安装操作系统后&#xff0c;安装相应运行时并能够运行星尘代理或幸运四叶草为通过条件。 测试平台&#xff1a;VMware Workstation 镜像来源&#xff1a;MSDN I Tell You 参考&#xff1a; .NET Fram…

5-Kafka-replication(副本机制)概念

&#x1f504; Kafka 副本机制&#xff08;Replication&#xff09; 核心概念概念说明Replica (副本)分区的完整拷贝&#xff0c;分布在不同 BrokerReplication Factor副本总数&#xff08;含 Leader&#xff09;&#xff0c;生产环境建议 ≥3Leader Replica处理所有读写请求&a…

langgraph的ReAct应用

一、什么是langgraph的ReActLangGraph 中的 ReAct&#xff08;Reasoning Acting&#xff09;代理是一种结合推理与行动能力的 AI 代理架构&#xff0c;通过动态决策链实现复杂任务处理。以下是其核心要点及实践指南。1、ReAct 代理的核心原理1.1工作流程&#xff1a;ReAct 代理…

一个编辑功能所引发的一场知识探索学习之旅(JavaScript、HTML)

文章目录一个编辑功能所引发的一场知识探索学习之旅&#xff08;JavaScript、HTML&#xff09;1. 一个编辑功能案例2. 知识点探索学习3. 参考资料一个编辑功能所引发的一场知识探索学习之旅&#xff08;JavaScript、HTML&#xff09; 1. 一个编辑功能案例 HTML&#xff1a; &l…

kali制作Windows木马

环境描述&#xff1a;攻击机&#xff1a;Kali-2025实验靶机&#xff1a;Windows11不要攻击他人&#xff0c;这只是网络安全实验还是一样获取IP地址制作好之后开服务&#xff0c;上传下载在靶机右键保留下载记得把防火墙&#xff0c;安全中心关了否则无法下载之后就可以kali控制…

从零实现一个GPT 【React + Express】--- 【1】初始化前后端项目,实现模型接入+SSE

摘要 本系列文章主要是实现一个能够对话以及具有文生图等功能的模型应用。主要UI界面会参考chat-gpt,豆包等系列应用。模型使用的是gpt开源的大模型。 如果你是一个前端开发工程师需要一个自己的开源项目&#xff0c;可以学习这个系列的文章&#xff0c;不需要有很完整的后端…