当前位置: 首页 > article >正文

简识MySQL的InnoDB Locking锁的分类

( 参考官方网页: MySQL :: MySQL 5.7 Reference Manual :: 14.7.1 InnoDB Locking)

一、InnoDB Locking锁的分类:

锁的分类英文缩写
共享锁Shared LocksS
排他锁Exclusive LocksX
意向共享锁Intention Shared LocksIS
意向排他锁Intention Exclusive LocksIX
记录锁Record Locks-
间隙锁Gap Locks-
下一键值锁(临键锁)Next-Key Locks-
插入意向锁Insert Intention Locks-
自动插入锁(自增锁)AUTO-INC Locks-

以下是对各类锁的具体说明:

  1. 共享锁(S锁):允许持有共享锁的事务读取一行数据,但不允许修改或删除。在MySQL的InnoDB引擎中,它是行级锁的一种。
  2. 排他锁(X锁):允许持有排他锁的事务更新或删除一行数据,同时阻止其他事务读取、修改或删除该行数据。在MySQL的InnoDB引擎中,它也是行级锁的一种。
  3. 意向共享锁(IS锁):表示一个事务打算在表的单独数据行上设置共享锁。它是表级锁,用于锁定表,以表示稍后将对表中的某些行加共享锁。
  4. 意向排他锁(IX锁):表示一个事务打算在表的单独数据行上设置排他锁。它也是表级锁,用于锁定表,以表示稍后将对表中的某些行加排他锁。
  5. 记录锁:索引记录上的一个锁,锁住单个行记录。在InnoDB中,即使表上没有定义索引,也会创建一个隐式簇索引,并用该索引进行记录锁定。
  6. 间隙锁:索引记录之间间隙上的锁,或第一个索引记录之前或最后一个索引记录之后间隙上的锁。间隙锁是“纯粹禁止的”,它们只是阻止其他事务往指定间隙插入数据,而不阻止不同事务在同一个间隙上获取间隙锁。
  7. 下一键值锁(临键锁):Record Lock和Gap Lock的结合,锁定一个范围,并且锁定记录本身。这种锁在InnoDB中用于防止幻读现象。
  8. 插入意向锁:间隙锁的一种,专门针对insert操作。当多个事务需要向同一个间隙中插入数据时,插入意向锁允许这些事务并行插入,而不会互相阻塞。
  9. 自动插入锁(自增锁):一种特殊的表级别锁,专门针对事务插入AUTO_INCREMENT类型的列。当一个事务正在向表中插入值时,其他事务必须等待,以便第一组事务插入的行接收到连续的主键值。

这些锁机制共同构成了InnoDB强大的并发控制功能,使得MySQL数据库能够在高并发环境下稳定运行。

二、InnoDB中部分锁的举例说明:

1. 共享锁(S锁)

共享锁允许多个事务同时读取同一行数据,但不能修改该数据。

示例

  • 事务1开始,并在id = 1的行上放置共享锁:SELECT * FROM your_table WHERE id = 1 LOCK IN SHARE MODE;
  • 事务2开始,也可以在id = 1的行上放置共享锁并查询:SELECT * FROM your_table WHERE id = 1 LOCK IN SHARE MODE;

在这个例子中,两个事务都可以同时对id = 1的行加共享锁并读取数据。

2. 排他锁(X锁)

排他锁允许事务独占一行数据,其他事务既不能读取也不能修改。

示例

  • 事务1开始,并在id = 2的行上放置排他锁:SELECT * FROM your_table WHERE id = 2 FOR UPDATE;
  • 事务2开始,尝试在同一行查询(会被阻塞,因为有排他锁):SELECT * FROM your_table WHERE id = 2;

在这个例子中,事务1在id = 2的行上放置了排他锁,事务2尝试读取这一行时就会被阻塞,直到事务1提交或回滚。

3. 意向锁(IS锁和IX锁)

意向锁用于表示事务想要在更高级别上获取锁(如表级锁)。意向锁是表级别的锁,不与行级锁冲突。

示例(意向共享锁IS):

  • 事务1开始,先在表上放置意向共享锁,表示想要获取表级共享锁:LOCK TABLE your_table IN SHARE MODE;
  • 事务2开始,尝试直接在表上进行独占操作(会被阻塞,因为有表级的意向共享锁):LOCK TABLE your_table IN EXCLUSIVE MODE;

在这个例子中,事务1先在表上放置了意向共享锁,事务2尝试获取表的排他锁时就会被阻塞。

示例(意向排他锁IX):

  • 事务1开始执行SELECT ... FOR UPDATE语句,此时会对所查询的记录加排他锁,并先对表加意向排他锁。

4. 记录锁

记录锁用于锁定单个行记录。

示例

  • 假设表your_table有字段idname,事务1开始并更新id = 3的行,会在该行上放置记录锁:UPDATE your_table SET name = 'new_name' WHERE id = 3;
  • 事务2开始,尝试更新同一行(会被阻塞,因为有记录锁):UPDATE your_table SET name = 'another_name' WHERE id = 3;

在这个例子中,事务1在id = 3的行上放置了记录锁,事务2尝试更新同一行时就会被阻塞。

5. 间隙锁

间隙锁用于锁定索引记录之间的“间隙”,但不锁定索引记录本身。

示例

  • 假设表your_tableid字段是索引,且有值1、3、5。事务1开始,查询id在1到3之间(不包含1和3)的数据并加锁,会在这个间隙上加间隙锁:SELECT * FROM your_table WHERE id > 1 AND id < 3 FOR UPDATE;
  • 事务2开始,尝试插入id = 2的数据(会被阻塞,因为有间隙锁):INSERT INTO your_table (id, name) VALUES (2, 'new_entry');

在这个例子中,事务1在1和3之间的间隙上加了间隙锁,事务2尝试插入id = 2的数据时就会被阻塞。

6. 下一键值锁(临键锁)

临键锁是记录锁和间隙锁的组合,用于锁定一个索引记录及其前面的间隙。

示例

  • 假设表your_tableid字段是索引,且有值1、3、5。事务1开始,查询id = 3的数据并加锁,会在id = 3的记录及其前面的间隙上加临键锁:SELECT * FROM your_table WHERE id = 3 FOR UPDATE;
  • 事务2开始,尝试插入id = 2的数据(会被阻塞,因为有临键锁锁定了id = 3前面的间隙):INSERT INTO your_table (id, name) VALUES (2, 'new_entry');
  • 事务2尝试更新id = 3的数据(会被阻塞,因为有临键锁锁定了id = 3的记录):UPDATE your_table SET name = 'updated_name' WHERE id = 3;

在这个例子中,事务1在id = 3的记录及其前面的间隙上加了临键锁,事务2尝试插入或更新时都会被阻塞。

7. 插入意向锁

插入意向锁是间隙锁的一种,专门针对insert操作。多个事务在同一个索引、同一个范围区间插入记录时,如果插入的位置不冲突,不会阻塞彼此。

示例(假设与间隙锁示例中的表结构和数据相同):

  • 事务1在1和3之间的间隙上尝试插入id = 2的数据(加插入意向锁)。
  • 事务2也在1和3之间的间隙上尝试插入id = 2.5的数据(加插入意向锁,与事务1不冲突)。

在这个例子中,尽管事务1和事务2都在同一个间隙上尝试插入数据,但由于它们插入的位置不冲突(一个是2,一个是2.5),因此它们可以并行插入而不会互相阻塞。

8. 自动插入锁(自增锁)

自增锁是一种特殊的表级别锁,专门针对事务插入AUTO_INCREMENT类型的列。当一个事务正在向表中插入值时,其他事务必须等待,以便第一组事务插入的行接收到连续的主键值。

示例

  • 假设有数据表t(id AUTO_INCREMENT, name),数据表中有数据:1, shenjian;2, zhangsan;3, lisi。
  • 事务A先执行(还未提交):insert into t(name) values('xxx');会得到一条(4, xxx)的记录。
  • 事务B后执行:insert into t(name) values('ooo');此时需要等待事务A提交后才能继续执行,因为InnoDB在RR隔离级别下使用自增锁来解决幻读问题。

在这个例子中,事务A先执行插入操作并获得了自增锁,因此事务B必须等待事务A提交后才能继续执行插入操作,以确保插入的主键值是连续的。

这些示例展示了InnoDB中各种锁的使用场景和工作方式。在实际应用中,需要根据具体的业务需求和并发控制要求来选择合适的锁类型。

(望各位潘安、各位子健不吝赐教!多多指正!🙏)


http://www.kler.cn/a/503225.html

相关文章:

  • Java Bean Validation 不适用Spring的情况下自定义validation注解
  • ssh2详细使用步骤,以及常用方法介绍
  • 通过外部化 `config.properties` 文件更换数据库配置
  • java项目之智慧农贸信息化管理平台(ssm+mybatis+mysql)
  • Java Web开发进阶——错误处理与日志管理
  • 回归预测 | MATLAB实RVM-Adaboost相关向量机集成学习多输入单输出回归预测
  • ue5 设置角色属性(生命值,蓝条值,能量值)c++
  • 基于WebRTC实现音视频通话
  • day01-HTML-CSS——基础标签样式表格标签表单标签
  • 斯坦福大学李飞飞教授团队ARCap: 利用增强现实反馈收集高质量的人类示教以用于机器人学习
  • 安装软件缺少msvcp110.dll怎么办?出现dll丢失的解决方法
  • LeetCode热题100(哈希篇)
  • unity学习18:unity里的 Debug.Log相关
  • 如何使用 Excel 进行多元回归分析?
  • 【数据结构】C语言顺序栈和链式栈的使用
  • 科技快讯 | 华为余承东2025新年信;教育部拟同意设置福耀科技大学等本科院校;我国成功发射一箭10星
  • <C++学习> C++ Boost 字符串操作教程
  • Day31补代码随想录20250110贪心算法5 56.合并区间|738.单调递增的数字|968.监控二叉树(可跳过)
  • LoRaWAN节点学习笔记
  • ASP.NET Core - 日志记录系统(一)
  • leetcode 面试经典 150 题:快乐数
  • 云服务信息安全管理体系认证,守护云端安全
  • npm、yarn、pnpm包安装器差异性对比
  • 深度学习中的卷积神经网络(CNN):原理与应用详解
  • 如何使用虚拟机连接到SSH
  • 【0x005B】HCI_Write_Default_Erroneous_Data_Reporting命令详解