MySQL 的意向锁(Intention Locks)原理详解

1. 背景:为什么需要意向锁?

        MySQL 中意向锁的主要作用是用于支持行级锁表级锁的并存,特别是在 InnoDB 存储引擎中。InnoDB 提供了行级锁,而在某些场景下,数据库系统仍需要对整张表加锁,例如 LOCK TABLES 或 ALTER TABLE 操作。在这些场景中,如果没有意向锁机制,系统需要扫描所有行级锁来判断是否可以安全地加表锁,这会严重影响性能。

        为了解决这一问题,意向锁应运而生。意向锁是一种表级锁,用于指示事务将要或已经在某些行上加锁。它通过提供表级的锁定信息,避免了系统去逐行检查是否可以加表锁。

2. 意向锁的类型

InnoDB 支持两种类型的意向锁:

  • 意向共享锁(IS, Intention Shared):事务想要在表中加共享锁之前,必须先获得意向共享锁。
  • 意向独占锁(IX, Intention Exclusive):事务想要在表中加排他锁之前,必须先获得意向独占锁。

共享锁(S 锁):允许读取但不允许修改数据。
排他锁(X 锁):允许读取和修改数据,并阻止其他事务加任何锁。

3. 意向锁的工作机制

意向锁的工作机制体现在事务与行级锁以及表级锁的协作上:

  • 当事务对表的某些行加行级锁时,它会先申请表级的意向锁(IS 或 IX),以告知其他事务该表上有行级锁存在。
  • 如果一个事务想要加表级的锁,它首先需要确认没有其他事务持有相冲突的意向锁或行锁。

例如:

  • 一个事务在表的某行上加了行级排他锁(X 锁),则必须先获得意向独占锁(IX)。如果另一个事务尝试给整张表加共享锁(S 锁),这个操作将会失败,因为 IX 锁与 S 锁冲突。
  • 反之,如果某事务只想对表的某些行加共享锁(S 锁),则它会申请意向共享锁(IS)。如果没有其他事务持有排他锁(如 X 锁),操作即可执行。

        通过意向锁,MySQL 在表级别快速判断是否可以加锁,而无需遍历行锁,极大提高了加表锁的效率。

4. 意向锁与其他锁的兼容矩阵

        InnoDB 中各种锁之间的兼容性决定了锁冲突的可能性。下表展示了意向锁与其他锁之间的兼容性关系:

ISIXSX
IS
IX
S
X
  •  表示兼容,允许同时存在。
  •  表示不兼容,不能同时存在。
5. 源代码层面的实现

        在 MySQL 的 InnoDB 存储引擎中,意向锁的实现主要体现在锁管理和事务管理模块中。我们从源码中进行分析:

5.1 锁管理模块

InnoDB 的锁管理模块位于 lock0lock.cc 文件中,主要函数有:

  • lock_rec_lock():负责加行级锁,包括排他锁(X 锁)和共享锁(S 锁)。在加锁之前,会先判断是否需要获取意向锁。
  • lock_table():负责加表级锁,其中也涉及到意向锁的获取过程。
5.2 意向锁的加锁过程

        在加行级锁时,MySQL 首先会根据事务需要加的锁类型来决定是否需要意向锁。假如事务需要在某行上加 X 锁(排他锁),系统会首先调用 lock_table() 来尝试给对应表加 IX 锁(意向排他锁)。如果意向锁冲突,则表明另一个事务已经持有冲突的锁(例如,另一个事务持有 S 锁),加锁失败。

相关源码逻辑如下:

bool lock_table(dict_table_t* table,   // 要加锁的表ulint type,            // 锁的类型(X 锁、S 锁、IX 锁、IS 锁等)trx_t* trx             // 当前事务
) {// 加锁过程,判断当前表是否已持有冲突的锁if (type == LOCK_IX || type == LOCK_IS) {// 检查是否存在冲突的锁,涉及到 IX 和 IS 的兼容性// 如果可以加锁,则加锁成功}return success;
}

5.3 锁兼容性检查

        意向锁与其他锁的兼容性通过 lock_mode_compat() 函数进行判断。该函数用于确定两种锁类型是否兼容,是否可以同时存在。

例如,IX 锁与 S 锁之间是互斥的,因此在加锁时会检查 IX 锁是否与现有的锁冲突:

bool lock_mode_compat(ulint mode1,  // 第一个锁的类型ulint mode2   // 第二个锁的类型
) {if ((mode1 == LOCK_IX && mode2 == LOCK_S) || (mode1 == LOCK_S && mode2 == LOCK_IX)) {// IX 锁与 S 锁冲突,返回不兼容return false;}// 其他兼容性检查逻辑return true;
}

5.4 表级锁与行级锁的协作

        当事务对某行进行加锁操作时,会先调用表级的意向锁机制,表级的意向锁通过 lock_table() 函数处理,而行级锁则通过 lock_rec_lock() 实现。加锁顺序为:

  1. 检查是否已经持有相应的意向锁,如果没有,则先申请意向锁。
  2. 然后再申请具体行的锁。
bool lock_rec_lock(ulint type,              // 锁的类型dict_index_t* index,     // 行所在的索引const buf_block_t* block,// 行所在的块ulint heap_no,           // 行的索引号trx_t* trx               // 当前事务
) {// 如果需要意向锁,则首先调用 lock_table() 加表锁if (need_intention_lock(type)) {if (!lock_table(index->table, LOCK_IX, trx)) {return false;  // 加表意向锁失败}}// 接下来加行级锁// 锁管理器会检查是否与现有的行锁冲突return lock_rec_add_to_queue(type, block, heap_no, trx);
}

6. 意向锁在事务中的表现

        事务在获取行级锁时,首先获取表级的意向锁,只有在表级意向锁不与其他事务冲突时,行级锁才能继续加上。这种机制保证了行级锁与表级锁之间的有效协调,从而避免了事务之间的冲突。


总结:

  • 意向锁是为了提高 MySQL 锁管理效率而设计的,允许 MySQL 在表级快速判断是否可以加锁。
  • 两种意向锁类型:意向共享锁(IS)和意向独占锁(IX),用于表示事务想要加的行级锁类型。
  • 源码实现表现在 lock_table() 和 lock_rec_lock() 等函数中,意向锁通过检查锁的兼容性确保事务在行级和表级加锁的正确性。
  • 意向锁的作用是避免在加表锁时遍历所有行锁,从而大幅提高系统性能。

        通过意向锁,MySQL 能有效地管理复杂的锁冲突场景,特别是在行级锁和表级锁同时存在时提供了明确的锁定层次,防止冲突并保持高效的锁操作。

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

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

相关文章

mysql 13 MySQL基于规则的优化

01.条件化简 我们编写的查询语句的搜索条件本质上是一个表达式,这些表达式可能比较繁杂,或者不能高效的执行, MySQL的查询优化器会为我们简化这些表达式。为了方便大家理解,我们后边举例子的时候都使用诸如 a 、 b 、 c 之类的简…

shell——正则表达式入门

目录 一、常规匹配 二、特殊字符 ^ $ . * 字符区间 \ 三、示例 shell中总是会需要对文本字符串做各种各样的剪切拼接等操作,除了 basename 和 dirname 这种简单的函数外,还可以用正则表达式,定义模糊匹配的筛选规则 一、常规匹配 管…

深入探讨 Spring 中的自定义注解及其使用场景

在现代 Java 开发中,注解(Annotation)作为一种元数据形式,极大地简化了开发者的代码配置和逻辑实现。Spring 框架充分利用了注解的功能,实现了依赖注入、事务管理、AOP(面向切面编程)等核心特性…

Pyqt5设计打开电脑摄像头+可选择哪个摄像头(如有多个)

目录 专栏导读库的安装代码介绍完整代码总结 专栏导读 🌸 欢迎来到Python办公自动化专栏—Python处理办公问题,解放您的双手 🏳️‍🌈 博客主页:请点击——> 一晌小贪欢的博客主页求关注 👍 该系列文…

【C++】——list 容器的解析与极致实现

人的一切痛苦,本质上都是对自己的无能的愤怒。 —— 王小波 目录 1、list 介绍 2、list的使用 2.1 list 的构造 2.2 iterator 的使用 2.3 list 的修改 2.4一些特殊接口 2.5 迭代器失效问题 3、实现list 3.1底层结构 结点类 list类 迭代器类 3.2功能接…

【优选算法篇】在分割中追寻秩序:二分查找的智慧轨迹

文章目录 C 二分查找详解:基础题解与思维分析前言第一章:热身练习1.1 二分查找基本实现解题思路图解分析C代码实现易错点提示代码解读 1.2 在排序数组中查找元素的第一个和最后一个位置解题思路1.2.1 查找左边界算法步骤:图解分析C代码实现 1…

git clone报错fatal: pack has bad object at offset 186137397: inflate returned 1

git clone报错fatal: pack has bad object at offset 186137397: inflate returned 1 逐步拷贝 https://stackoverflow.com/questions/27653116/git-fatal-pack-has-bad-object-at-offset-x-inflate-returned-5 https://www.cnblogs.com/Lenbrother/p/17726195.html https://…

在UE引擎中使用spine动画(1)

注意事项,spine的版本必须和UE插件的版本相同。 1.最重要的是“修改骨架名称。(影响在UE引擎中的资产名称) 2.导出操作(把非必要的数据取消掉,可能会影响UE导入)。 3.纹理打包(一般默认&#…

程序员:数字时代的先锋

随着科技的不断进步,程序员这一职业群体逐渐成为社会中不可或缺的一部分。他们以智慧和汗水为世界带来更多的便捷与创新。今天,我们将庆祝1024程序员节,这是一个向全球程序员们表达敬意和感激的节日。让我们一同走进程序员的内心世界&#xf…

Vue学习笔记(八、v-model双向绑定)

与v-bind只能实现单向绑定不同&#xff0c;v-model可以实现数据的双向绑定&#xff0c;不过v-model只能用于表单元素中&#xff0c;例如&#xff1a;input(radio,text,address,email...) 、select、checkbox、textarea。 下面代码是一个v-model双向绑定的演示&#xff1a; <…

数字分组求偶数和

问题描述 小M面对一组从 1 到 9 的数字&#xff0c;这些数字被分成多个小组&#xff0c;并从每个小组中选择一个数字组成一个新的数。目标是使得这个新数的各位数字之和为偶数。任务是计算出有多少种不同的分组和选择方法可以达到这一目标。 numbers: 一个由多个整数字符串组…

[ 钓鱼实战系列-基础篇-7 ] 一篇文章教会你搭建邮件钓鱼服务器-1

&#x1f36c; 博主介绍 &#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 _PowerShell &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 &#x1f389;点赞➕评论➕收藏 养成习…

js.杨辉三角和分发饼干

1&#xff0c;链接&#xff1a;118. 杨辉三角 - 力扣&#xff08;LeetCode&#xff09; 题目&#xff1a; 给定一个非负整数 numRows&#xff0c;生成「杨辉三角」的前 numRows 行。 在「杨辉三角」中&#xff0c;每个数是它左上方和右上方的数的和。 示例 1: 输入: numRows …

代码随想录算法训练营第二十五天|Day25 回溯算法

491.递增子序列 https://programmercarl.com/0491.%E9%80%92%E5%A2%9E%E5%AD%90%E5%BA%8F%E5%88%97.html 视频讲解&#xff1a;https://www.bilibili.com/video/BV1EG4y1h78v 思路 int* path; int pathTop; int** ans; int ansTop; int* length; void copy() {int* tempPath …

动态规划-子序列问题——300.最长递增子序列

1.题目解析 题目来源&#xff1a;300.最长递增子序列——力扣 测试用例 2.算法原理 1.状态表示 首先创建一个与数组大小相同的dp表&#xff0c;此时dp[i]表示的是&#xff1a;以第i个位置为结尾的所有子序列中最长递增子序列的长度 2.状态转移方程 此时第i个位置一定是最长递…

国家能源集团携手海康威视研发攻克融合光谱煤质快检技术

10月24日&#xff0c;在国家能源集团准能集团黑岱沟露天煤矿&#xff0c;安装于准能选煤厂785商品煤胶带机中部的煤质快检核心设备&#xff0c;正在对当天装车外运的商品煤煤质进行实时检测。仅两分钟后&#xff0c;涵盖发热量、水分、灰分、硫分等多项指标的数据信息已传输到到…

六.python面向对象

学过C或者Java的同学一定了解过面向对象的相关内容&#xff0c;编程语言一般分为两种设计方式&#xff1a;面向对象、面向过程&#xff0c;早期的编程语言多是面向过程的&#xff0c;由多个过程组合在一起&#xff0c;而Python在设计的时候就是一种面向对象的语言&#xff0c;因…

Room新手入门

Room Room 是所谓的 ORM&#xff08;对象关系映射&#xff09;库 依赖 在项目级 build.gradle 文件中&#xff0c;在 ext 代码块中定义 room_version。 ext {kotlin_version "1.6.20"nav_version "2.4.1"room_version 2.4.2 }在应用级 build.gradle…

【JavaEE初阶】深入理解TCP协议中的封装分用以及UDP和TCP在网络编程的区别

前言 &#x1f31f;&#x1f31f;本期讲解关于TCP/UDP协议的原理理解~~~ &#x1f308;上期博客在这里&#xff1a;【JavaEE初阶】入门视角-网络原理的基础理论的了解-CSDN博客 &#x1f308;感兴趣的小伙伴看一看小编主页&#xff1a;GGBondlctrl-CSDN博客 &#x1f525; …

【Spring】关于Spring中aware相关接口的作用

Aware 接口的回调方法是在 Bean 实例化之后调用的。具体来说&#xff0c;这些回调方法是在依赖注入完成后&#xff0c;但在 Bean 完全初始化之前调用的。这是 Spring 容器管理 Bean 生命周期的一部分 完成了属性赋值之后&#xff0c;Spring会执行一些回调&#xff0c;包括&…