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

深入理解MySQL 鎖之從全局鎖到死鎖檢測(cè)的問(wèn)題

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

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

鎖的全景圖

理解 MySQL 鎖,可以從三個(gè)維度切入:

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

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

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

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

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

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

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

意向鎖:表級(jí)別的"打招呼"

當(dāng)你準(zhǔn)備給某一行加 X 鎖時(shí),MySQL 會(huì)先在表級(jí)別加一個(gè)意向排他鎖(IX)。

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

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

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

這是基于 B+ 樹(shù)的物理鎖,也是面試最高頻的考點(diǎn)。

記錄鎖(Record Lock)

精確鎖住索引樹(shù)上的某一個(gè)葉子節(jié)點(diǎn)。

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

間隙鎖(Gap Lock)

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

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

臨鍵鎖(Next-Key Lock)

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

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

記住一個(gè)準(zhǔn)則:MySQL 的鎖是加在"索引"上的,而不是加在"行"上的。

即使你建表時(shí)沒(méi)有主鍵也沒(méi)有唯一索引,InnoDB 也會(huì)在后臺(tái)自動(dòng)創(chuàng)建一個(gè)隱藏列 RowID 作為聚簇索引。

這意味著:

  • 查詢(xún)命中主鍵索引 → 精準(zhǔn)的記錄鎖
  • 沒(méi)命中索引導(dǎo)致全表掃描 → 鎖升級(jí)為覆蓋全表的 Next-Key Lock
  • REPEATABLE READ 下間隙鎖防止幻讀;READ COMMITTED 下基本沒(méi)有間隙鎖

實(shí)操:三步看透鎖

不需要背書(shū),開(kāi)兩個(gè)終端窗口就能直觀感受。

第一步:制造"對(duì)峙"

窗口 A——開(kāi)啟事務(wù)并加鎖:

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

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

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

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

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

SELECT * FROM performance_schema.data_locks;

你會(huì)清晰地看到:哪個(gè)線(xiàn)程持有鎖,鎖的是哪棵 B+ 樹(shù),是 X 鎖還是 GAP 鎖,甚至能看到鎖的具體 pk_id。

第三步:分析死鎖

SHOW ENGINE INNODB STATUS;

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

死鎖:原理與破局

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

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

經(jīng)典死鎖場(chǎng)景

時(shí)間點(diǎn)事務(wù) A事務(wù) 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 的死鎖檢測(cè)機(jī)制

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

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

代碼層面的預(yù)防策略

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

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

高頻問(wèn)題補(bǔ)充

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

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

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

結(jié)論:永遠(yuǎn)不要在線(xiàn)上高峰期對(duì)大表做 ALTER TABLE,除非你明確評(píng)估了 MDL 的影響。

自增鎖(AUTO-INC Locks)

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

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

悲觀鎖 vs 樂(lè)觀鎖

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

  • 悲觀鎖SELECT ... FOR UPDATE,先占位再干活,適合寫(xiě)沖突頻繁的場(chǎng)景
  • 樂(lè)觀鎖:通過(guò)版本號(hào)控制,UPDATE ... SET version = version + 1 WHERE id = 1 AND version = ?,不鎖行,提交時(shí)檢查是否被修改過(guò),適合讀多寫(xiě)少的場(chǎng)景

總結(jié)

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

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    MySQL主鍵生成的四種方式及對(duì)比詳解

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

最新評(píng)論

新源县| 秀山| 抚远县| 泸水县| 顺义区| 阜康市| 庆安县| 新昌县| 普陀区| 乌兰浩特市| 宣威市| 武陟县| 祁门县| 新乐市| 黔江区| 南昌市| 涿州市| 翼城县| 玉门市| 沅江市| 昔阳县| 邵阳市| 饶河县| 克拉玛依市| 集贤县| 永川市| 乐平市| 榆林市| 集安市| 保康县| 湟中县| 乳山市| 元谋县| 寿阳县| 秭归县| 宝鸡市| 永新县| 衡南县| 册亨县| 天水市| 镇赉县|