mysql 間隙鎖和臨鍵鎖原理

間隙鎖產(chǎn)生的背景

備注: 本文使用的 MySQL 版本是: 8.0.13

隔離級(jí)別:可重復(fù)讀(RR)

存儲(chǔ)引擎:Innodb

以下面的表為例子進(jìn)行說(shuō)明

CREATE TABLE `tb` ( `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `a` (`a`)) ENGINE=InnoDB;
insert into tb values(0,0,0),(10,10,10),(20,20,20),(30,30,30),(40,40,40),(50,50,50);

間隙鎖的產(chǎn)生來(lái)自于 InnboDB 引擎在可重復(fù)讀的級(jí)別基礎(chǔ)上執(zhí)行當(dāng)前讀時(shí)出現(xiàn)的幻讀問(wèn)題。下面來(lái)分析一下幻讀的例子,假如沒(méi)有間隙鎖的話,那么會(huì)出現(xiàn)下面的現(xiàn)象:

sessionA sessionB
T1 begin;
select * from tb where a = 10 for update;
返回:(10,10,10)
T2 insert into tb value(2,10,11);
T3 select * from tb where a = 10 for update;
返回:(10,10,10),(2,10,11)
T4 commit;

如上表如示,是基于沒(méi)有間隙鎖的假設(shè),sessionA 事務(wù)內(nèi)執(zhí)行兩次相同的當(dāng)前讀返回的數(shù)據(jù)不一樣,出現(xiàn)幻讀的現(xiàn)象。因?yàn)?2,2,10)這條記錄在原本的數(shù)據(jù)并不存在,行鎖就鎖不住,因此誕生間隙鎖。

間隙鎖加鎖規(guī)則

間隙鎖和行鎖合稱 next-key lock,每一個(gè) next-keylock 是前開(kāi)后閉區(qū)間,如: (0,10]

  • 原則 1:加鎖的基本單位是 next-key lock。

  • 原則 2:加鎖是基于索引的,查找過(guò)程中訪問(wèn)到的對(duì)象才會(huì)加鎖

  • 優(yōu)化 1:索引上的等值查詢,給唯一索引加鎖的時(shí)候,next-key lock 退化為行鎖

  • 優(yōu)化 2:索引上的等值查詢,向右遍歷時(shí)且最后一個(gè)值不滿足等值條件的時(shí)候,next-key lock 退化為間隙鎖。

分析上面例子

select * from tb where b = 10 for update;

  1. 加鎖的基于索引的
    因?yàn)?b 不是索引,索引走的是主鍵索引,加鎖就是加在主鍵索引上

  2. 加鎖范圍

    遍歷主鍵索引,發(fā)現(xiàn) b=10 時(shí),需要在前后記錄之間加鎖,所以在前一主鍵記錄(0,0,0)和本記錄之間加鎖(0,10],在后一條主鍵記錄(20,20)和本記錄之間加鎖 (10,20]。然后繼續(xù)向右遍歷,判斷 b=20,!=10,滿足優(yōu)化 2 規(guī)則,next-key lock 退化為間隙鎖,變成(10,20)。同時(shí) b=10 加了行鎖,匯總鎖范圍: (0,20),針對(duì) id 主鍵

  3. 間隙鎖與“往這個(gè)間隙插入操作”沖突

    因?yàn)樯厦嬷麈I id 鎖的范圍是(0,20),因此插入(2,2,10)中 主鍵 2 屬于鎖范圍,因此阻塞

    注意: 線程之間的間隙鎖是不沖突的

查詢條件走二級(jí)索引例子

sessionA sessionB
T1 begin;
select id from tb where a = 20 for update;
T2 場(chǎng)景 1:insert into tb values(5,11,11);//阻塞
場(chǎng)景 2: insert into tb values(15,10,8);//阻塞
場(chǎng)景 3:insert into tb values(17,9,1);//成功
場(chǎng)景 4: insert into tb values(25,35,88);//成功
T3 commit;

首先看看sessionA的執(zhí)行計(jì)劃,發(fā)現(xiàn)用到覆蓋索引

explain select id from tb where a = 20 for update;

  1. 因?yàn)闂l件走了 a 索引,查詢字段 id 在索引 a中,用到的覆蓋索引,索引在搜索過(guò)程中,只用到索引 a,所以只會(huì)在索引 a 中間隙鎖,同時(shí)命中條件對(duì)應(yīng)的主鍵也要加上行鎖,所以主鍵 id=20 被加了行鎖。

  2. 間隙鎖加在索引 a 上的范圍是(10,30),為了更加深度理解加鎖范圍,如下圖:

image.png

場(chǎng)景 1:插入到索引 a 時(shí),要插入是索引是(11,5),屬于(a=10,id=10)和(a=30,id=30)之間的鎖范圍,所以阻塞

場(chǎng)景 2、3、4 同理分析得出結(jié)論

查詢條件走主鍵索引例子

sessionA sessionB
T1 begin;
select * from tb where a = 10 for update;
T2 場(chǎng)景 1:insert into tb values(5,11,11);//阻塞
場(chǎng)景 2: insert into tb values(15,10,8);//阻塞
場(chǎng)景 3:insert into tb values(17,9,1);//阻塞(主鍵上的鎖)
場(chǎng)景 4: insert into tb values(25,35,88);//成功
場(chǎng)景 5:insert into tb values(5,5,5);//阻塞(主鍵上的鎖)
T3 commit;

本例子跟《查詢條件走二級(jí)索引例子》區(qū)別在于 sessionA 是 select * ,因此需要回到主鍵索引查詢所有字段,掃描了主鍵索引,所以也會(huì)在掃描到的索引進(jìn)行加 next-key lock。該語(yǔ)句回表一次,掃描到是行是 id=10,所以加鎖是(0,10],(10,20),因此 sessionA 一共加了鎖是索引 a 的(10,30)和主鍵索引的(0,20)。

  • 場(chǎng)景 1,2 跟上一個(gè)例子一樣命中索引 a 和主鍵索引的鎖范圍,阻塞
  • 場(chǎng)景 3 因?yàn)?17 屬于主鍵索引(10,20)之間,所以被阻塞
  • 場(chǎng)景 4 不用索引 a 和主鍵索引的鎖范圍,所以成功。
  • 場(chǎng)景 5,沒(méi)命中索引 a 的鎖,但是命中了主鍵上的鎖范圍,所以被主鍵索引上的鎖阻塞

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1,Mysql X鎖和S鎖。 1)概念:利用數(shù)據(jù)庫(kù)本身提供的鎖機(jī)制(行級(jí)鎖)來(lái)實(shí)現(xiàn),鎖定該行數(shù)據(jù)。trx_rows...
    沐兮_d64c閱讀 7,726評(píng)論 0 3
  • 當(dāng)一個(gè)系統(tǒng)訪問(wèn)量上來(lái)的時(shí)候,不只是數(shù)據(jù)庫(kù)性能瓶頸問(wèn)題了,數(shù)據(jù)庫(kù)數(shù)據(jù)安全也會(huì)浮現(xiàn),這時(shí)候合理使用數(shù)據(jù)庫(kù)鎖機(jī)制就顯得異...
    初來(lái)的雨天閱讀 3,695評(píng)論 0 22
  • 間隙鎖(Gap Lock)是Innodb在提交下為了解決幻讀問(wèn)題時(shí)引入的鎖機(jī)制,(下面的所有案例沒(méi)有特意強(qiáng)調(diào)都使用...
    小亮__閱讀 108,746評(píng)論 28 72
  • 參考資料:極客時(shí)間《MySQL實(shí)戰(zhàn)45講》 1 基礎(chǔ)架構(gòu) 存儲(chǔ)引擎層負(fù)責(zé)數(shù)據(jù)的存儲(chǔ)和提取。其架構(gòu)模式是插件式的,支...
    IM后海大鯊魚(yú)閱讀 1,027評(píng)論 0 0
  • 1.鎖分類 當(dāng)多個(gè)事務(wù)或進(jìn)程訪問(wèn)同一個(gè)資源時(shí),為了保證數(shù)據(jù)的一致性就會(huì)用到鎖機(jī)制,在MySQL中鎖有多種不同的分類...
    我叫王小事兒閱讀 421評(píng)論 0 1

友情鏈接更多精彩內(nèi)容