深入剖析MySQL锁机制,多事务并发场景锁竞争

一、隐藏字段对 InnoDB 的行锁(Record Lock)与间隙锁(Gap Lock)的影响


1. 隐藏字段与锁的三大核心影响

类型影响维度描述
DB_TRX_IDMVCC 可见性控制决定是否读取当前版本,或在加锁时避开不可见版本(影响加锁粒度)
DB_ROLL_PTR构建多版本链影响锁等待、加锁时的记录版本选择(间接决定是否锁冲突)
隐式 RowID行定位与加锁无主键时 RowID 作为唯一定位字段,对行锁加锁范围关键

2. DB_TRX_ID 与行锁冲突判断

✅ 场景:事务并发修改同一行数据

  1. 读取事务依据当前事务的 ReadView,根据 DB_TRX_ID 判断该版本是否“可见”。

  2. 写入事务加锁时,若当前行的 DB_TRX_ID ≠ 当前事务,则可能出现“当前锁冲突”或“等待前版本释放”。

  3. 若版本不可见,可能绕过该记录不加锁(如 RC 隔离级别下的 Next-Key Lock)

🎯 例子:RC 与 RR 加锁行为不同

-- T1: 开启事务,修改一行
BEGIN;
UPDATE user SET age = 30 WHERE id = 100;-- T2: 并发事务,尝试更新相同 id
BEGIN;
UPDATE user SET age = 35 WHERE id = 100; -- 被阻塞

解释

  • InnoDB 通过 DB_TRX_ID 比较当前行的修改者是谁;

  • 若与当前事务不同 → 加锁或等待;

  • Read Committed 级别可能跳过不可见版本的加锁(幻读可能出现)。


3. DB_ROLL_PTR 与版本链上的加锁行为

✅ 场景:一行数据有多个历史版本

  • DB_ROLL_PTR 指向 undo log(之前的版本);

  • 在 RR 隔离级别下,InnoDB 可能根据 ReadView 沿着版本链找到合适版本读取;

  • 加锁时只锁当前版本(最新版本),但读取时可能读取旧版本。

🎯 幻读控制与间隙锁相关:

-- T1: 查询 WHERE age > 30
-- T2: 在该范围内插入新记录
-- T1: 再次查询,同样语句,发现多了新记录 → 幻读

为了防止 T2 插入“未来可能匹配”的记录,InnoDB 使用 Gap LockNext-Key Lock 对间隙加锁。

是否加锁哪些行/间隙,DB_ROLL_PTR 决定了当前记录是否属于可见范围 → 是否参与锁计算。


4. 隐式 RowID 与加锁定位(Record Lock)

✅ 场景:无主键表

CREATE TABLE t (name VARCHAR(100)
) ENGINE=InnoDB;
  • InnoDB 自动创建一个 6 字节 RowID(隐式主键)

  • 聚簇索引以 RowID 为 key 建树

  • 所有辅助索引也指向 RowID

🔐 加锁行为:

  • 对于无主键表,InnoDB 通过 RowID 精确加锁;

  • 行锁定位依赖 RowID;

  • 辅助索引加锁回表时,也依赖 RowID 判断目标行;

📌 所以:如果你不建主键,行锁仍然是可精确的,但依赖的是隐式 RowID


5. 隐藏字段如何影响三种锁类型

锁类型是否依赖隐藏字段说明
行锁(Record)RowID, DB_TRX_ID判断是否锁冲突、锁定位
间隙锁(Gap)DB_TRX_ID, ROLL_PTR是否跳过某些版本,加锁哪些间隙
Next-Key Lock✅ 混合依赖加锁实际记录+其间隙

6. 实战举例:两个事务交错更新记录

-- T1
BEGIN;
SELECT * FROM user WHERE age > 30 FOR UPDATE;-- T2
BEGIN;
INSERT INTO user(id, name, age) VALUES (5, 'Mike', 35);

🔍 解析:

  • T1 通过聚簇索引扫描记录,遇到每一行:

    • 检查 DB_TRX_ID,判断是否可见;

    • 依据可见版本决定加锁(Next-Key Lock → 行+间隙);

  • T2 插入时,必须检测新记录是否在 T1 加锁区间内 → 若是则阻塞;

即便某一行在 T1 的快照中不可见,但只要它是当前版本,T1 可能仍然加锁(受隔离级别控制)


7. 隐藏字段在锁机制中的作用

隐藏字段对锁的影响
DB_TRX_ID决定事务是否看到当前版本 → 影响加锁行为与锁冲突判定
ROLL_PTR构造历史版本链,决定 MVCC 可见性 → 影响是否需要加锁
Row ID无主键表唯一标识 → 用于加锁定位、辅助索引回表行锁
RecordHeader是否删除标志 → 已删除记录是否参与加锁由此决定

二、深入剖析行级锁和间隙锁

主要将深入剖析:

  1. ✅ 各种锁类型的定义与底层机制

  2. ✅ 锁的触发场景与加锁策略

  3. ✅ InnoDB 加锁流程与隐藏字段的关系

  4. ✅ 常见加锁案例分析(如幻读、唯一键冲突)

  5. ✅ 可视化锁冲突与调试技巧


1. InnoDB 锁类型总览

锁类型粒度描述
✅ 行锁(Record Lock)精确锁住一行记录(聚簇索引记录)
✅ 间隙锁(Gap Lock)锁住两个索引记录之间的“间隙”,不含记录本身
✅ Next-Key Lock行锁 + 间隙锁,锁住记录及其前后间隙
🔄 插入意向锁(Insert Intention Lock)特殊锁标记插入意图,不是互斥锁,但参与死锁检测

2. 行锁(Record Lock)

📌 定义:

锁定聚簇索引中的一条具体记录。

🔧 加锁条件:

  • 明确通过 主键 / 唯一键 精确定位某条记录;

  • 触发语句通常为:

    SELECT * FROM t WHERE id = 1 FOR UPDATE;
    UPDATE t SET name = 'x' WHERE id = 1;
    

🧬 底层机制:

  • 锁记录基于 B+ 树中记录的物理位置;

  • 锁信息存储在 锁数据结构 lock_t 中,并挂载到事务事务结构 trx_t 的锁链表。


3. 间隙锁(Gap Lock)

📌 定义:

锁住两条索引记录之间的范围(gap),但不包括已有的记录

🔧 加锁场景:

  • 防止幻读:防止其他事务在该范围内插入新记录;

  • RR(Repeatable Read)下执行范围条件的 SELECT ... FOR UPDATEDELETEUPDATE

  • 示例:

-- 假设表中已有 id = 100, 200
SELECT * FROM t WHERE id > 100 AND id < 200 FOR UPDATE;
-- 锁定的是 (100, 200) 的间隙,不包括100和200

🧬 底层机制:

  • 锁住 B+ 树中的两个键值之间的指针区域;

  • 无具体记录,但会在锁表中以特殊“GAP”标志表示。


4. Next-Key Lock(默认使用)

📌 定义:

Next-Key Lock = Record Lock + Gap Lock
即锁住 记录本身 + 其前面的间隙

🔧 加锁场景:

  • 默认隔离级别为 RR(可重复读) 时,InnoDB 对范围查询使用 Next-Key Lock;

  • 作用:

    • 防止幻读(新插入记录“幻出现”)

    • 保证范围读一致性

🌰 举例:

-- 表中已有 id = 100, 200
SELECT * FROM t WHERE id >= 100 AND id < 200 FOR UPDATE;

此时锁住范围:

  • 间隙 (100, 200)

  • 记录 id = 100


5. 锁的触发机制

1️⃣ 锁的决定因素

影响项描述
SQL 类型SELECT ... FOR UPDATE / DELETE / UPDATE 会加锁
隔离级别RR 使用 Next-Key Lock,RC 只锁记录本身
访问条件主键精确命中加 Record Lock,范围条件加 Gap Lock/Next-Key Lock
是否命中索引走索引加行锁;走全表扫描加表锁

2️⃣ 加锁时机

  • 执行语句解析完成、访问 B+ 树查找记录时;

  • 遇到匹配记录时,根据事务隔离级别加锁;

  • 加锁时会检查 DB_TRX_ID,判断该版本是否对当前事务可见;

    • 若不可见(由其他事务正在修改),可能等待或加锁历史版本(undo 构建视图)


6. 锁冲突案例剖析

📍 幻读问题(RR下通过 Gap Lock/Next-Key Lock 解决)

-- T1
BEGIN;
SELECT * FROM t WHERE age > 30 FOR UPDATE;-- T2
INSERT INTO t(age) VALUES (35);  -- 被阻塞(因 T1 已加锁间隙)

📍 唯一键冲突(加锁 + 意向锁)

-- T1
INSERT INTO t(id, name) VALUES (100, 'A');-- T2
INSERT INTO t(id, name) VALUES (100, 'B');  -- 被阻塞(同一主键)

📍 死锁触发

-- T1
UPDATE t SET name = 'A' WHERE id = 1;-- T2
UPDATE t SET name = 'B' WHERE id = 2;-- 然后相互更新对方的记录,将触发死锁

7. 加锁调试技巧

✅ 查看当前锁情况:

SELECT * FROM information_schema.innodb_locks;
SELECT * FROM performance_schema.data_locks;

✅ 死锁日志:

SHOW ENGINE INNODB STATUS \G

可定位谁等待谁、加了什么锁、是否超时或死锁。


8. 锁类型与机制全图

                       ┌────────────────────┐│   SQL 语句类型      │└────────────────────┘│┌────────▼────────┐│ 是否走索引?     │──否──▶ 表锁(意外情况)└────────┬────────┘│是┌────────▼────────┐│ 锁定条件类型     │└────────┬────────┘精确匹配     │    范围匹配│       ▼┌──────▼──────┐   ┌────────────┐│ 行锁        │   │ Next-Key 锁 │└─────────────┘   └────────────┘↑                 ↑RC 可降为 Record Lock    RR 加间隙锁避免幻读

三、深入剖析 MySQL InnoDB 中多事务并发场景下的锁竞争与回滚机制

1. 核心概念概览

概念描述
锁竞争多个事务试图访问同一资源(记录/间隙)但互斥,形成等待或死锁
回滚机制事务执行失败、冲突或死锁时,撤销已执行部分操作,恢复一致状态
死锁检测与回滚策略InnoDB 采用 Wait-for Graph 检测死锁,选择某个事务回滚释放锁

2. 典型并发冲突与回滚案例


📍 案例 1:更新相同记录引发锁等待

表结构:
CREATE TABLE account (id INT PRIMARY KEY,balance INT
) ENGINE=InnoDB;
INSERT INTO account VALUES (1, 1000), (2, 2000);
并发场景:
-- Session A
START TRANSACTION;
UPDATE account SET balance = balance - 100 WHERE id = 1;-- Session B
START TRANSACTION;
UPDATE account SET balance = balance + 100 WHERE id = 1;  -- 被阻塞
🔍 分析:
  • id=1 被 Session A 先锁定(行锁)。

  • Session B 尝试更新同一记录,被阻塞。

  • 若 A 提交或回滚,B 才能继续执行。


📍 案例 2:幻读冲突引发间隙锁竞争(RR隔离)

-- Session A
START TRANSACTION;
SELECT * FROM account WHERE id BETWEEN 1 AND 3 FOR UPDATE;-- Session B
INSERT INTO account VALUES (3, 3000);  -- 阻塞
🔍 分析:
  • A 加了 Next-Key Lock:锁定了 id=1 和 id=2 以及间隙 (2,∞)。

  • 插入 id=3 的操作冲突于间隙锁,Session B 阻塞。

  • A 提交或回滚后,B 才能插入。


📍 案例 3:死锁发生,InnoDB 检测并回滚

-- Session A
START TRANSACTION;
UPDATE account SET balance = balance - 100 WHERE id = 1;-- Session B
START TRANSACTION;
UPDATE account SET balance = balance - 100 WHERE id = 2;-- Session A
UPDATE account SET balance = balance + 100 WHERE id = 2;  -- 阻塞-- Session B
UPDATE account SET balance = balance + 100 WHERE id = 1;  -- 死锁
🔍 死锁图:
A 等待 B 释放 id=2
B 等待 A 释放 id=1
⇒ 形成死锁
💥 InnoDB 处理机制:
  • InnoDB 启动“死锁检测器”,构建 Wait-for Graph;

  • 选择一个开销更小的事务(通常是等待时间短的),执行自动回滚;

  • 抛出错误:

    ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction
    

3. InnoDB 回滚机制详解

✅ 回滚触发点:

  1. 显式 ROLLBACK

  2. 死锁检测回滚事务

  3. 唯一键/外键冲突

  4. DDL 失败隐式回滚

✅ 回滚操作步骤:

  1. 利用隐藏字段 DB_ROLL_PTR 回溯 Undo Log 链;

  2. 撤销所有已变更记录(覆盖旧值);

  3. 释放已加锁资源(行锁、间隙锁);

  4. 标记事务为 ROLLING BACK 状态;

✅ 相关结构:

结构描述
Undo Log存储旧版本数据用于回滚与 MVCC
TRX结构体保存事务状态及锁信息链表
Lock Hash Table管理锁持有和等待信息

4. 锁冲突 & 回滚实验演示命令

🔧 查看当前锁持有状态

-- 查看当前锁
SELECT * FROM information_schema.innodb_locks;-- 查看锁等待关系
SELECT * FROM information_schema.innodb_lock_waits;

🔧 查看死锁日志

SHOW ENGINE INNODB STATUS\G;

查看最新一次死锁信息、涉及记录、被回滚的事务等。


5. 最佳实践建议

场景建议
多事务更新热点记录使用悲观锁 + 乐观重试机制,避免死锁
范围锁定使用主键精准定位,减少间隙锁
防止死锁保证事务更新顺序一致,如永远先更新 id小的记录
并发冲突排查使用 innodb_status + performance_schema.data_locks 分析锁链和回滚

6. 总结

关键点内容
锁竞争由事务访问冲突资源引发,可能阻塞
回滚自动或手动撤销事务操作,使用 Undo 日志还原
死锁检测InnoDB 内部维护等待图,自动检测并终止代价小的事务
调试工具information_schemaSHOW ENGINE INNODB STATUS、慢查询日志等

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

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

相关文章

以SMMUv2为例,使用Trace32可视化操作SMMU的常用命令详解

Trace32支持一系列的SMMU命令&#xff0c;可以帮助用户更好地配置、查看和分析SMMU。换句话说&#xff0c;就是让SMMU的配置变得可视化。 在添加SMMU实例之前&#xff0c;需要选择一个CPU来激活该SMMU实例的相关命令。Trace32让SMMU的配置可视化的本质是&#xff0c;操纵CPU读取…

将数据库表导出为C#实体对象

数据库方式 use 数据库;declare TableName sysname 表名 declare Result varchar(max) /// <summary> /// TableName /// </summary> public class TableName {select Result Result /// <summary>/// CONVERT(NVARCHAR(500), ISNULL(ColN…

CSS 预处理器与工具

目录 CSS 预处理器与工具1. Less主要特性 2. Sass/SCSS主要特性 3. Tailwind CSS主要特性 4. 其他工具PostCSSCSS Modules 5. 选择建议 CSS 预处理器与工具 1. Less Less 是一个 CSS 预处理器&#xff0c;它扩展了 CSS 语言&#xff0c;添加了变量、嵌套规则、混合&#xff0…

this.$set() 的用法详解(Vue响应式系统相关)

1. 什么是 this.$set()&#xff1f; this.$set(target, key, value) 是 Vue 2 中提供的一个方法&#xff0c;用于向响应式对象中动态添加属性&#xff0c;确保新加的属性同样是响应式的。 2. 为什么需要它&#xff1f; Vue 2 的响应式系统基于 Object.defineProperty&#…

【HarmonyOS Next之旅】DevEco Studio使用指南(三十)

目录 1 -> 部署云侧工程 2 -> 通过CloudDev面板获取云开发资源支持 3 -> 通用云开发模板 3.1 -> 适用范围 3.2 -> 效果图 4 -> 总结 1 -> 部署云侧工程 可以选择在云函数和云数据库全部开发完成后&#xff0c;将整个云工程资源统一部署到AGC云端。…

如何配置nginx解决前端跨域请求问题

我们以一个简单的例子模拟不同情况下产生的跨域问题以及解决方案。假设在http://127.0.0.1:8000的页面调用接口 fetch(http://127.0.0.1:8003/api/data)常看到的错误“Access to fetch at ‘http://127.0.0.1:8003/api/data’ from origin ‘http://localhost:8000’ has been…

React Hooks 指南:何时使用 useEffect ?

在 React 的函数组件中&#xff0c;useEffect Hook 是一个强大且不可或缺的工具。它允许我们处理副作用 (side effects)——那些在组件渲染之外发生的操作。但是&#xff0c;什么时候才是使用 useEffect 的正确时机呢&#xff1f;让我们深入探讨一下&#xff01; 什么是副作用…

bat批量去掉本文件夹中的文件扩展名

本文本夹内 批量去掉本文件夹中的文件扩展名 假如你有一些文件&#xff0c;你想去掉他们的扩展名 有没有方便的办法呢 今天我们就分享一种办法。 下面&#xff0c;就来看看吧。 首先我们新建一个记事本&#xff0c;把名字改为&#xff0c;批量去掉本文件夹中的文件扩展名.txt 然…

STM32标准库-输入捕获

一、输入捕获 1.简介 IC&#xff08;Input Capture&#xff09;输入捕获输入 捕获模式下&#xff0c;当通道输入引脚出现指定电平跳变时&#xff0c;当前CNT的值将被锁存到CCR中&#xff0c;可用于测量PWM波形的频率、占空比、脉冲间隔、电平持续时间等参数 每个高级定时器和…

在linux系统上搭建git服务器(ssh协议)

1.在windows上生成RSA密钥对 ssh-keygen -t rsa -b 2048 -C"git用户名/邮箱地址" 命令执行后会在 C:\Users\${windows登录账户}\.ssh 目录下生成密钥对 其中 id_rsa 为私钥&#xff0c;id_rsa.pub 为公钥 2.在 linux 系统上登记公钥 vim ~/.ssh/authorized_keys…

RAG检索系统的两大核心利器——Embedding模型和Rerank模型

在RAG系统中&#xff0c;有两个非常重要的模型一个是Embedding模型&#xff0c;另一个则是Rerank模型&#xff1b;这两个模型在RAG中扮演着重要角色。 Embedding模型的作用是把数据向量化&#xff0c;通过降维的方式&#xff0c;使得可以通过欧式距离&#xff0c;余弦函数等计算…

stm32内存踩踏一例

1、问题描述 程序运行过程中&#xff0c;发现显示的内容乱了&#xff0c;如下图所示&#xff1a; 2、问题分析 此原因产生是由于将一个函数提前引起的&#xff0c;单步跟踪检查问题 运行过此函数后变量的地址改变了&#xff1f;被调函数能改变调用函数的变量地址&#xff1f…

Selenium的底层原理

Selenium 底层主要依赖于 WebDriver 协议&#xff08;即 W3C WebDriver 规范&#xff0c;早期也有 JSON Wire Protocol&#xff09;来实现对浏览器的远程控制&#xff0c;其核心架构可以分为以下几层&#xff1a; Selenium 客户端&#xff08;Client Library&#xff09; 支持多…

前端高频面试题2:浏览器/计算机网络

本专栏相关链接 前端高频面试题1&#xff1a;HTML/CSS 前端高频面试题2&#xff1a;浏览器/计算机网络 前端高频面试题3&#xff1a;JavaScript 1.什么是强缓存、协商缓存&#xff1f; 强缓存&#xff1a; 当浏览器请求资源时&#xff0c;首先检查本地缓存是否命中。如果命…

MATLAB-电偶极子所产出的电磁场仿真

% 清除工作区 clear all % 用户输入 a input(输入点电荷的位置如[1,0,1;2,0,2]表示位置在(1,0,1),(2,0,2): ); Q input(输入点电荷的电荷量&#xff0c;-表示电性&#xff0c;如[1,-1]: ); a1 input(电场线角度间隔: ); % 角度间隔 % 设置绘图范围 xmin min(a(:,1)) - 4;…

混合云数据库连接问题:本地与云实例的兼容性挑战

关键词:混合云数据库,混合云架构,数据库连接问题,网络策略,兼容性挑战,权限冲突,防火墙,VPN,ExpressRoute,Direct Connect,SQL Server,MySQL,PostgreSQL,Azure SQL Database,AWS RDS 随着企业数字化转型的深入,混合云架构正成为主流选择。它结合了本地数据中心…

pikachu靶场通关笔记16 CSRF关卡02-CSRF(POST)

目录 一、CSRF原理 二、源码分析 三、渗透实战 1、构造CSRF链接 &#xff08;1&#xff09;登录 &#xff08;2&#xff09;bp设置inception on &#xff08;3&#xff09;修改个人信息 &#xff08;4&#xff09;构造CSRF链接 2、模拟受害者登录 3、诱导受害者点击 …

CAD2025安装教程与资源下载

软件下载 软件名称&#xff1a;CAD2025软件语言&#xff1a;简体中文软件大小&#xff1a;2.69G系统要求&#xff1a;Windows10或更高&#xff0c;32/ 64位操作系统硬件要求&#xff1a;CPU2GHz &#xff0c;RAM4G或更高下载链接&#xff1a; 链接&#xff1a;https://pan.qua…

SpringBoot离线应用的5种实现方式

在当今高度依赖网络的环境中&#xff0c;离线应用的价值日益凸显。无论是在网络不稳定的区域运行的现场系统&#xff0c;还是需要在断网环境下使用的企业内部应用&#xff0c;具备离线工作能力已成为许多应用的必备特性。 本文将介绍基于SpringBoot实现离线应用的5种不同方式。…

数据类型 -- 字符

在C中&#xff0c;字符型&#xff08;char&#xff09;用于存储单个字符&#xff0c;如字母、数字、符号等。字符型是最基本的数据类型之一&#xff0c;常用于处理文本、字符数组&#xff08;字符串&#xff09;等场景。 1. 基本类型 • char&#xff1a;标准字符类型&#x…