深入剖析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
繁體地址,請注明出處:http://hk.pswp.cn/web/82874.shtml
英文地址,請注明出處:http://en.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…