最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

深入理解MySQL 鎖之從全局鎖到死鎖檢測的問題

 更新時間:2026年02月26日 11:30:29   作者:Flobby529  
mysql的鎖并不是單一的概念,本文從三個維度對InnoDB鎖體系進行系統(tǒng)梳理,幫你在實戰(zhàn)和面試中建立清晰的知識框架,感興趣的朋友跟隨小編一起看看吧

MySQL 的鎖并不是單一的概念。本文從三個維度對 InnoDB 鎖體系進行系統(tǒng)梳理,幫你在實戰(zhàn)和面試中建立清晰的知識框架。

鎖的全景圖

理解 MySQL 鎖,可以從三個維度切入:

維度鎖的類型核心目的
粒度劃分全局鎖、表級鎖、行級鎖控制鎖定的數(shù)據(jù)范圍(InnoDB 以行鎖為主)
兼容性劃分共享鎖 (S)、排他鎖 (X)決定多個事務能否同時操作同一塊數(shù)據(jù)
鎖的算法記錄鎖、間隙鎖、臨鍵鎖決定在 B+ 樹的哪個位置加鎖

第一層:鎖的粒度——你在哪里加鎖?

鎖級別類比對應 SQL 場景影響
全局鎖封鎖整棟大樓,不準進出FLUSH TABLES WITH READ LOCK(全庫備份)業(yè)務全線停擺,極少手動使用
表級鎖包下整個樓層搞裝修LOCK TABLES 或元數(shù)據(jù)鎖 (MDL)影響整張表,并發(fā)能力差
行級鎖鎖住具體的房間UPDATE ... WHERE id = 1InnoDB 的看家本領(lǐng),并發(fā)最高

第二層:鎖的兼容性——S 鎖與 X 鎖

這是所有鎖的基礎(chǔ)邏輯:

  • 共享鎖(S 鎖 / 讀鎖):我能讀,你也能讀,但大家都別想改。觸發(fā)方式:SELECT ... FOR SHARE
  • 排他鎖(X 鎖 / 寫鎖):我要改,誰也別想碰。觸發(fā)方式:UPDATE / DELETE / SELECT ... FOR UPDATE

需要注意的是,普通的 SELECT 是不加鎖的(快照讀)。只有顯式加鎖語句才會觸發(fā)。

意向鎖:表級別的"打招呼"

當你準備給某一行加 X 鎖時,MySQL 會先在表級別加一個意向排他鎖(IX)。

為什么需要它?想象一張 1.6 億行的表,如果另一個事務想加表鎖,沒有意向鎖的話,數(shù)據(jù)庫得遍歷 1.6 億行去檢查有沒有行鎖。有了意向鎖,只需要看一眼表頭就知道了——這是一種空間換時間的策略。

關(guān)鍵特性:意向鎖之間是兼容的,意向鎖和行鎖之間也是兼容的。它唯一不兼容的是表級鎖。

第三層:行鎖的三種算法——InnoDB 的精華

這是基于 B+ 樹的物理鎖,也是面試最高頻的考點。

記錄鎖(Record Lock)

精確鎖住索引樹上的某一個葉子節(jié)點。

-- 精準打擊,只鎖 pk_id = 10 這一行
SELECT * FROM t_mqtt_log WHERE pk_id = 10 FOR UPDATE;

間隙鎖(Gap Lock)

鎖住兩個索引記錄之間的"縫隙",不包括記錄本身。目的是防止幻讀——阻止其他事務往這個縫隙里插入新數(shù)據(jù)。

類比:在 101 房間和 105 房間之間的走廊上放一個"施工中"的牌子,別人想在 102 插入一個新房間?對不起,走廊被封了。

臨鍵鎖(Next-Key Lock)

記錄鎖 + 間隙鎖的組合,鎖住一個范圍并且包含記錄本身。這是 InnoDB 在 REPEATABLE READ 隔離級別下的默認行鎖算法

鎖與索引的核心關(guān)系

記住一個準則:MySQL 的鎖是加在"索引"上的,而不是加在"行"上的。

即使你建表時沒有主鍵也沒有唯一索引,InnoDB 也會在后臺自動創(chuàng)建一個隱藏列 RowID 作為聚簇索引。

這意味著:

  • 查詢命中主鍵索引 → 精準的記錄鎖
  • 沒命中索引導致全表掃描 → 鎖升級為覆蓋全表的 Next-Key Lock
  • REPEATABLE READ 下間隙鎖防止幻讀;READ COMMITTED 下基本沒有間隙鎖

實操:三步看透鎖

不需要背書,開兩個終端窗口就能直觀感受。

第一步:制造"對峙"

窗口 A——開啟事務并加鎖:

BEGIN;
SELECT * FROM t_mqtt_log WHERE pk_id = 10 FOR UPDATE;

窗口 B——嘗試修改同一行(會被阻塞):

UPDATE t_mqtt_log SET type = 1 WHERE pk_id = 10;
-- 此時 B 會卡住,等待 A 釋放鎖

第二步:查看"案發(fā)現(xiàn)場"

在第三個窗口執(zhí)行:

SELECT * FROM performance_schema.data_locks;

你會清晰地看到:哪個線程持有鎖,鎖的是哪棵 B+ 樹,是 X 鎖還是 GAP 鎖,甚至能看到鎖的具體 pk_id。

第三步:分析死鎖

SHOW ENGINE INNODB STATUS;

LATEST DETECTED DEADLOCK 一欄,你會看到完整的死鎖現(xiàn)場:誰在等誰,誰最后被 MySQL 犧牲掉了。

死鎖:原理與破局

死鎖的發(fā)生需要滿足四個必要條件(Coffman 條件):

  1. 互斥:資源在一段時間內(nèi)只能被一個事務鎖定
  2. 占有且等待:事務已持有鎖,同時又在請求另一個被其他事務持有的鎖
  3. 不可搶占:事務持有的鎖在事務完成前不能被強制釋放
  4. 循環(huán)等待:A 等 B,B 等 A,形成環(huán)

經(jīng)典死鎖場景

時間點事務 A事務 B
T1UPDATE users SET name='A' WHERE id=1;(拿到 ID=1 的鎖)
T2UPDATE users SET name='B' WHERE id=2;(拿到 ID=2 的鎖)
T3UPDATE users SET name='A2' WHERE id=2;(阻塞,等待 B 釋放 ID=2)
T4UPDATE users SET name='B2' WHERE id=1;(死鎖!B 試圖拿 ID=1,但 A 持有)

InnoDB 的死鎖檢測機制

InnoDB 通過 Wait-for Graph(等待關(guān)系圖) 主動檢測死鎖:

  1. 維護一張鎖等待關(guān)系圖,一旦發(fā)現(xiàn)環(huán),立即判定死鎖
  2. 選擇代價最小的事務進行回滾(通常是更新行數(shù)最少、Undo Log 最少的那個)
  3. 被回滾的事務釋放所有鎖,另一個事務繼續(xù)執(zhí)行
  4. 應用程序收到經(jīng)典報錯:Deadlock found when trying to get lock; try restarting transaction

代碼層面的預防策略

無法完全杜絕死鎖,但以下策略能極大降低概率:

  1. 固定訪問順序:所有業(yè)務邏輯都按相同順序操作資源(先 ID=1 再 ID=2),從根源上打破循環(huán)等待
  2. 大事務拆小:事務執(zhí)行時間越長,持有鎖的時間越長,撞車概率越大
  3. 善用索引:沒命中索引時鎖會升級(Next-Key Lock 甚至鎖全表),鎖范圍越大,死鎖概率越高
  4. 降低隔離級別:如果業(yè)務允許,從 RR 降到 RC 可以消滅大部分間隙鎖,減少死鎖

高頻問題補充

元數(shù)據(jù)鎖(MDL)——線上事故高發(fā)區(qū)

MDL 不是加在數(shù)據(jù)上的,而是加在表結(jié)構(gòu)上的。一個典型的災難場景:

  1. 事務 A 執(zhí)行了一個慢查詢 SELECT(未結(jié)束),持有 MDL 讀鎖
  2. 你執(zhí)行 ALTER TABLE 加字段,申請 MDL 寫鎖,被 A 阻塞
  3. 之后所有新的 SELECT 都會被這個 ALTER TABLE 堵住
  4. 連接池瞬間爆炸,服務雪崩

結(jié)論:永遠不要在線上高峰期對大表做 ALTER TABLE,除非你明確評估了 MDL 的影響。

自增鎖(AUTO-INC Locks)

對于高并發(fā)插入場景(比如 t_mqtt_log 每秒插入幾千次),所有事務都要搶下一個自增 ID。InnoDB 通過自增鎖來協(xié)調(diào),關(guān)鍵調(diào)優(yōu)參數(shù)是 innodb_autoinc_lock_mode

  • 0(傳統(tǒng)模式):語句級鎖,并發(fā)最差
  • 1(連續(xù)模式):簡單插入用輕量鎖,批量插入用語句級鎖(MySQL 5.x 默認)
  • 2(交錯模式):完全并發(fā),性能最好,但批量插入的自增值可能不連續(xù)(MySQL 8.0 默認)

悲觀鎖 vs 樂觀鎖

這是業(yè)務邏輯層面的鎖策略選擇:

  • 悲觀鎖SELECT ... FOR UPDATE,先占位再干活,適合寫沖突頻繁的場景
  • 樂觀鎖:通過版本號控制,UPDATE ... SET version = version + 1 WHERE id = 1 AND version = ?,不鎖行,提交時檢查是否被修改過,適合讀多寫少的場景

總結(jié)

知識點核心要點
鎖粒度全局鎖 > 表級鎖 > 行級鎖,InnoDB 以行鎖為主
S 鎖 / X 鎖共享鎖允許并發(fā)讀,排他鎖獨占讀寫
意向鎖表級標記,避免加表鎖時逐行檢查
記錄鎖精確鎖住索引上的一條記錄
間隙鎖鎖住記錄間的縫隙,防止幻讀
臨鍵鎖記錄鎖 + 間隙鎖,InnoDB 默認行鎖算法
鎖加在索引上沒命中索引 → 鎖升級,范圍越大死鎖概率越高
死鎖檢測Wait-for Graph 檢測環(huán),回滾代價最小的事務
MDL表結(jié)構(gòu)鎖,高峰期 ALTER TABLE 可致服務雪崩

到此這篇關(guān)于深入理解 MySQL 鎖:從全局鎖到死鎖檢測的文章就介紹到這了,更多相關(guān)mysql全局鎖到死鎖檢測內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • MySQL數(shù)據(jù)庫表修復 MyISAM

    MySQL數(shù)據(jù)庫表修復 MyISAM

    這篇文章主要介紹了MySQL數(shù)據(jù)庫表修復 MyISAM ,需要的朋友可以參考下
    2014-06-06
  • 小型Drupal數(shù)據(jù)庫備份以及大型站點MySQL備份策略分享

    小型Drupal數(shù)據(jù)庫備份以及大型站點MySQL備份策略分享

    為了防止web服務器出現(xiàn)故障而引起的數(shù)據(jù)丟失,數(shù)據(jù)庫備份顯得非常重要,以免出現(xiàn)重大損失。本文分析研究一下小型的Drupal站的備份策略以及大型站點的mysql備份策略
    2014-11-11
  • mysql之關(guān)于CST和GMT時區(qū)時間轉(zhuǎn)換方式

    mysql之關(guān)于CST和GMT時區(qū)時間轉(zhuǎn)換方式

    這篇文章主要介紹了mysql之關(guān)于CST和GMT時區(qū)時間轉(zhuǎn)換方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-10-10
  • MySQL8新特性:持久化全局變量的修改方法

    MySQL8新特性:持久化全局變量的修改方法

    這篇文章主要給大家介紹了關(guān)于MySQL 8新特性:持久化全局變量的修改的相關(guān)內(nèi)容,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考價值,需要的朋友們下面隨著小編來一起學習學習吧
    2018-07-07
  • Win10下mysql 8.0.20 安裝配置方法圖文教程

    Win10下mysql 8.0.20 安裝配置方法圖文教程

    這篇文章主要為大家詳細介紹了Win10下mysql 8.0.20 安裝配置方法圖文教程,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • mysql實現(xiàn)遞歸查詢的方法示例

    mysql實現(xiàn)遞歸查詢的方法示例

    本文主要介紹了mysql實現(xiàn)遞歸查詢的方法示例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-07-07
  • MySQL如何處理InnoDB并發(fā)事務中的間隙鎖死鎖

    MySQL如何處理InnoDB并發(fā)事務中的間隙鎖死鎖

    這篇文章主要為大家介紹了MySQL如何處理InnoDB并發(fā)事務中的間隙鎖死鎖,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-10-10
  • 將圖片儲存在MySQL數(shù)據(jù)庫中的幾種方法

    將圖片儲存在MySQL數(shù)據(jù)庫中的幾種方法

    今天小編就為大家分享一篇關(guān)于將圖片儲存在MySQL數(shù)據(jù)庫中的幾種方法,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧
    2019-03-03
  • MySQL中的當前讀和快照讀的區(qū)別

    MySQL中的當前讀和快照讀的區(qū)別

    在MySQL中,當前讀和快照讀是事務中的兩種重要的讀取方式,當前讀,即鎖定讀,會對讀取的行記錄加鎖,確保數(shù)據(jù)一致性,兩者的主要區(qū)別在于鎖定機制、數(shù)據(jù)一致性、并發(fā)性能和幻讀問題,理解這些差異有助于根據(jù)業(yè)務需求選擇合適的讀取方式,保證數(shù)據(jù)庫的事務隔離性和一致性
    2024-09-09
  • MySQL主鍵生成的四種方式及對比詳解

    MySQL主鍵生成的四種方式及對比詳解

    在數(shù)據(jù)庫設(shè)計中,主鍵(Primary Key)的選擇至關(guān)重要,它不僅是數(shù)據(jù)行的唯一標識,還直接影響查詢效率、數(shù)據(jù)存儲甚至系統(tǒng)架構(gòu)的擴展性,本文給大家分析了常見四種主鍵ID生成的方式,需要的朋友可以參考下
    2025-03-03

最新評論

大竹县| 如东县| 莱西市| 内乡县| 贡觉县| 集贤县| 阳谷县| 郁南县| 卢氏县| 嵩明县| 色达县| 金乡县| 景洪市| 鄂温| 呼和浩特市| 广平县| 兴和县| 内江市| 临武县| 承德市| 贵溪市| 观塘区| 兴仁县| 信阳市| 九龙县| 商水县| 德昌县| 江源县| 东辽县| 来凤县| 沙洋县| 大理市| 聂荣县| 永仁县| 武山县| 新蔡县| 仁化县| 嘉荫县| 岐山县| 离岛区| 东海县|