欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

簡(jiǎn)單了解 MySQL 中相關(guān)的鎖

 更新時(shí)間:2021年05月25日 09:33:02   作者:SH的全棧筆記  
這篇文章主要介紹了簡(jiǎn)單了解 MySQL 中相關(guān)的鎖,重點(diǎn)介紹InnoDB中的鎖相關(guān)知識(shí),包括鎖的概念及分類(lèi)解析,對(duì)MySQL鎖相關(guān)感興趣的朋友跟隨小編一起看看吧

本文主要是帶大家快速了解 InnoDB 中鎖相關(guān)的知識(shí)

基礎(chǔ)概念解析和RocketMQ詳細(xì)的源碼解析

http://xiazai.jb51.net/202105/yuanma/RocketMQ_jb51.rar

為什么需要加鎖

首先,為什么要加鎖?我想我不用多說(shuō)了,想象接下來(lái)的場(chǎng)景你就能 GET 了。

你在商場(chǎng)的衛(wèi)生間上廁所,此時(shí)你一定會(huì)做的操作是啥?鎖門(mén)。如果不鎖門(mén),上廁所上著上著,啪一下門(mén)就被打開(kāi)了,可能大概也許似乎貌似有那么一丁點(diǎn)的不太合適。

數(shù)據(jù)也是一樣,在并發(fā)的場(chǎng)景下,如果不對(duì)數(shù)據(jù)加鎖,會(huì)直接破壞數(shù)據(jù)的一致性,并且如果你的業(yè)務(wù)涉及到錢(qián),那后果就更嚴(yán)重了。

鎖門(mén)表情包

鎖的分類(lèi)

在 InnoDB 中,都有哪些鎖?其實(shí)你應(yīng)該已經(jīng)知道了很多了,例如面試中會(huì)問(wèn)你存儲(chǔ)引擎 MyISAM 和 InnoDB 的區(qū)別,你會(huì)說(shuō) MyIASM 只有表鎖,但是 InnoDB 同時(shí)支持行鎖和表鎖。你可能還會(huì)被問(wèn)到樂(lè)觀鎖和悲觀鎖的區(qū)別是啥。

鎖的概念、名詞很多,如果你沒(méi)有對(duì)鎖構(gòu)建出一個(gè)完整的世界觀,那么你理解起來(lái)就會(huì)比較有阻礙,接下來(lái)我們把這些鎖給分一下類(lèi)。

按照鎖的粒度

按照鎖的粒度進(jìn)行劃分可以分為:

  • 表鎖
  • 行鎖

這里就不討論頁(yè)鎖了,頁(yè)鎖是 BDB(BerkeleyDB) 存儲(chǔ)引擎中才有的概念,我們這里主要討論 InnoDB 存儲(chǔ)引擎。

按照鎖的思想

按照加鎖的思想可以分為:

  • 悲觀鎖
  • 樂(lè)觀鎖

這里的悲觀、樂(lè)觀和你平時(shí)理解的名詞是同一個(gè)意思。樂(lè)觀鎖認(rèn)為大概率不會(huì)發(fā)生沖突,只在必要的時(shí)候加鎖。而悲觀鎖認(rèn)為大概率會(huì)沖突,所以無(wú)論是否必要加鎖都會(huì)執(zhí)行加鎖操作。

按照兼容性

按照兼容性可以把鎖劃分為:

  • 共享鎖
  • 排他鎖

被加上共享鎖的資源,能夠和其他人進(jìn)行共享,而如果被加上了排他鎖,其他人在拿不到這把鎖的情況下是無(wú)法進(jìn)行任何操作的。

按照鎖的實(shí)現(xiàn)

這里的實(shí)現(xiàn)就是 InnoDB 中具體的鎖的種類(lèi)了,分別有:

  • 意向鎖(Intention Locks)
  • 記錄鎖(Record Locks)
  • 間隙鎖(Gap Locks)
  • 臨鍵鎖(Next-Key Locks)
  • 插入意向鎖(Insert Intention Locks)
  • 自增鎖(AUTO-INC Locks)

即使按照這種分類(lèi)來(lái)對(duì)鎖進(jìn)行了劃分,看到了這么多的鎖的名詞可能仍然會(huì)有點(diǎn)懵。比如我SELECT ... FOR UPDATE 的時(shí)候到底加的是什么鎖?

我們應(yīng)該透過(guò)現(xiàn)象看本質(zhì),本質(zhì)是什么?本質(zhì)是鎖到底加在了什么對(duì)象上,而這個(gè)很好回答:

  • 加在了表上
  • 加在了行上

而對(duì)于加在行上的鎖,其本質(zhì)又是什么?本質(zhì)是將鎖加在了索引上。

意向鎖

在 InnoDB 中支持了不同粒度的鎖,行鎖和表鎖。例如lock tables命令就會(huì)持有對(duì)應(yīng)表的排他鎖。為了使多種不同粒度的鎖更實(shí)用,InnoDB 設(shè)計(jì)了意向鎖。

意向鎖是一種表級(jí)鎖,它表明了接下來(lái)的事務(wù)中,會(huì)使用哪種類(lèi)型的鎖,它有以下兩種類(lèi)型:

  • 共享意向鎖(IS) 表明該事務(wù)會(huì)打算對(duì)表中的記錄加共享鎖
  • 獨(dú)占意向鎖(IX) 則是加排他鎖

例如,select ... for share就是加的共享意向鎖,而SELECT .. FOR UPDATE則是加的獨(dú)占意向鎖。其規(guī)則如下:

  • 一個(gè)事務(wù)如果想要獲取某張表中某行的共享鎖,它必須先獲取該表的共享意向鎖,或者獨(dú)占意向鎖。
  • 同理,如果想獲取排他鎖,它必須先獲取獨(dú)占意向鎖

下圖是這幾種鎖的組合下相互互斥、兼容的情況

對(duì)照上面的表,在相互兼容的情況下,對(duì)應(yīng)的事務(wù)就能獲取鎖,但是如果不兼容則無(wú)法獲取鎖,直到不兼容的鎖釋放之后才能獲取。

看到這里你可能就會(huì)有問(wèn)題了,那既然意向鎖除了 LOCK TBALES 之外什么都不阻塞。那我要它何用?

還是通過(guò)例子,假設(shè)事務(wù) A 獲取了 student 表中 id = 100 這行的共享鎖,之后事務(wù) B 需要申請(qǐng) student 表的排他鎖。而這兩把鎖明顯是沖突的,而且還是對(duì)于同一行。

那 InnoDB 需要如何感知 A 獲取了這把鎖?遍歷整個(gè) B+ 樹(shù)嗎?不,答案就是意向鎖。事務(wù) B 申請(qǐng)寫(xiě)表的排他鎖時(shí),InnoDB 會(huì)發(fā)現(xiàn)事務(wù) A 已經(jīng)獲取了該表的意向共享鎖,說(shuō)明 student 表中已經(jīng)有記錄被共享鎖鎖住了。此時(shí)就會(huì)阻塞住。

并且,意向鎖除了像LOCK TABLES這種操作之外,不會(huì)阻塞其他任何操作。換句話說(shuō),意向鎖只會(huì)和表級(jí)別的鎖之間發(fā)生沖突,而不會(huì)和行級(jí)鎖發(fā)生沖突。因?yàn)橐庀蜴i的主要目的是為了表明有人即將、或者正在鎖定某一行。

就像你去圖書(shū)館找書(shū),你并不需要每個(gè)書(shū)架挨著挨著找,直接去服務(wù)臺(tái)用電腦一搜,就知道圖書(shū)館有沒(méi)有這本書(shū)。

記錄鎖

這就是記錄鎖,是行鎖的一種。記錄鎖的鎖定對(duì)象是對(duì)應(yīng)那行數(shù)據(jù)所對(duì)應(yīng)的索引。對(duì)索引不太清楚的可以看看這篇文章

當(dāng)我們執(zhí)行SELECT * FROM student WHERE id = 1 FOR UPDATE語(yǔ)句時(shí),就會(huì)對(duì)值為1的索引加上記錄鎖。至于要是一張表里沒(méi)有索引該怎么辦?這個(gè)問(wèn)題在上面提到的文章中也解釋過(guò)了,當(dāng)一張表沒(méi)有定義主鍵時(shí),InnoDB 會(huì)創(chuàng)建一個(gè)隱藏的RowID,并以此 RowID 來(lái)創(chuàng)建聚簇索引。后續(xù)的記錄鎖也會(huì)加到這個(gè)隱藏的聚簇索引上。

當(dāng)我們開(kāi)啟一個(gè)事務(wù)去更新 id = 1 這行數(shù)據(jù)時(shí),如果我們不馬上提交事務(wù),然后再啟一個(gè)事務(wù)去更新 id = 1 的行,此時(shí)使用 show engine innodb status查看,我們可以看到lock_mode X locks rec but not gap waiting的字樣。

X是排他鎖的意思,從這可以看出來(lái),記錄鎖其實(shí)也可以分為共享鎖、排他鎖模式。當(dāng)我們使用FOR UPDATE是排他,而使用LOCK IN SHARE MODE 則是共享。

而在上面字樣中出現(xiàn)的 gap 就是另一種行鎖的實(shí)現(xiàn)間隙鎖。

間隙鎖

對(duì)于間隙鎖(Gap Locks)而言,其鎖定的對(duì)象也是索引。為了更好的了解間隙鎖,我們舉個(gè)例子。

SELECT name FROM student WHERE age BETWEEN 18 AND 25 FOR UPDATE

假設(shè)我們?yōu)?age 建立了非聚簇索引,運(yùn)行該語(yǔ)句會(huì)阻止其他事務(wù)向 student 表中新增 18-25 的數(shù)據(jù),無(wú)論表中是否真的有 age 為 18-25 的數(shù)據(jù)。因?yàn)殚g隙鎖的本質(zhì)是鎖住了索引上的一個(gè)范圍,而 InnoDB 中索引在底層的B+樹(shù)上的存儲(chǔ)是有序的。

再舉個(gè)例子:

SELECT * FROM student WHERE age = 10 FOR UPDATE;

值得注意的是,這里的 age 不是唯一索引,就是一個(gè)簡(jiǎn)單的非聚簇索引。此時(shí)會(huì)給 age = 10 的數(shù)據(jù)加上記錄鎖,并且鎖定 age < 10 的 Gap。如果當(dāng)前這個(gè)事務(wù)不提交,其他事務(wù)如果要插入一條 age < 10 的數(shù)據(jù)時(shí),會(huì)被阻塞住。

間隙鎖是 MySQL 在對(duì)性能、并發(fā)綜合考慮之下的一種折中的解決方案,并且只在**可重復(fù)讀(RR)下可用,如果當(dāng)前事務(wù)的隔離級(jí)別為讀已提交(RC)**時(shí),MySQL會(huì)將間隙鎖禁用。

剛剛說(shuō)了,記錄鎖分為共享、排他,間隙鎖其實(shí)也一樣。但是不同于記錄鎖的一點(diǎn),共享間隙鎖、排他間隙鎖相互不互斥,這是怎么回事?

我們還是需要透過(guò)現(xiàn)象看到本質(zhì),間隙鎖的目的是什么?

為了防止其他事務(wù)在 Gap 中插入數(shù)據(jù)

那共享、排他間隙鎖在這個(gè)目標(biāo)上是一致的,所以是可以同時(shí)存在的。

臨鍵鎖

臨鍵鎖(Next-Key Locks)是 InnoDB 最后一種行鎖的實(shí)現(xiàn),臨鍵鎖實(shí)際上是記錄鎖和間隙鎖的組合。換句話說(shuō),臨鍵鎖會(huì)給對(duì)應(yīng)的索引加上記錄鎖,并且外加鎖定一個(gè)區(qū)間。

但是并不是所有臨鍵鎖都是這么玩的,對(duì)于下面的SQL:

SELECT * FROM student WHERE id = 23;

在這種情況下,id是主鍵,唯一索引,無(wú)論其他事務(wù)插入了多少數(shù)據(jù),id = 23這條數(shù)據(jù)永遠(yuǎn)也只有一條。此時(shí)再加一個(gè)間隙鎖就完全沒(méi)有必要了,反而會(huì)降低并發(fā)。所以,在使用的索引是唯一索引的時(shí)候,臨鍵鎖會(huì)降級(jí)為記錄鎖。

假設(shè)我們有10,20,30總共3條索引數(shù)據(jù)。那么對(duì)應(yīng)臨鍵鎖來(lái)說(shuō),可能鎖定的區(qū)間就會(huì)如下:

  • (∞, 10]
  • (10, 20]
  • (20, 30]
  • (30, ∞)

InnoDB 的默認(rèn)事務(wù)隔離級(jí)別為可重復(fù)讀(RR),在這個(gè)情況下,InnoDB 就會(huì)使用臨鍵鎖,以防止幻讀的出現(xiàn)。

簡(jiǎn)單解釋一下幻讀,就是在事務(wù)內(nèi),你執(zhí)行了兩次查詢(xún),第一次查詢(xún)出來(lái) 5 條數(shù)據(jù),但是第二次再查,居然查出了 7 條數(shù)據(jù),這就是幻讀。

可能你在之前的很多博客,或者面試八股文上,了解到過(guò) InnoDB 的RR事務(wù)隔離級(jí)別可以防止幻讀,RR防止幻讀的關(guān)鍵就是臨鍵鎖。

舉個(gè)例子,假設(shè) student 表中就兩行數(shù)據(jù),id分別為90和110.

SELECT * FROM student WHERE id > 100 FOR UPDATE;

當(dāng)執(zhí)行該 SQL 語(yǔ)句之后,InnoDB就會(huì)給區(qū)間 (90, 110] 和(110,∞) 加上間隙鎖,同時(shí)給 id=110 的索引加上記錄鎖。這樣以來(lái),其他事務(wù)就無(wú)法向這個(gè)區(qū)間內(nèi)新增數(shù)據(jù),即使 100 根本不存在。

插入意向鎖

接下來(lái)是插入意向鎖(Insert Intention Locks),當(dāng)我們執(zhí)行 INSERT 語(yǔ)句之前會(huì)加的鎖。本質(zhì)上是間隙鎖的一種。

還是舉個(gè)例子,假設(shè)我們現(xiàn)在有索引記錄10、20,事務(wù)A、B分別插入索引值為14、16的數(shù)據(jù),此時(shí)事務(wù)A和B都會(huì)用插入意向鎖鎖住 10-20 之間的 Gap,獲取了插入意向鎖之后就會(huì)獲取14、16的排他鎖。

此時(shí)事務(wù)A和B是不會(huì)相互阻塞的,因?yàn)樗麄儾迦氲氖遣煌男小?/p>

自增鎖

最后是自增鎖(AUTO-INC Locks),自增鎖的本質(zhì)是表鎖,較為特殊。當(dāng)事務(wù) A 向包含了 AUTO_INCREMENT 列的表中新增數(shù)據(jù)時(shí),就會(huì)持有自增鎖。而此時(shí)其他的事務(wù) B 則必須要等待,以保證事務(wù) A 取得連續(xù)的自增值,中間不會(huì)有斷層。

好了,通過(guò)下面鏈接獲取MQ學(xué)習(xí)資料,包含基礎(chǔ)概念解析和RocketMQ詳細(xì)的源碼解析,持續(xù)更新中,大家一定不要錯(cuò)過(guò)這份學(xué)習(xí)資料哦。

http://xiazai.jb51.net/202105/yuanma/RocketMQ_jb51.rar (必收藏)

以上就是簡(jiǎn)單了解 MySQL 中相關(guān)的鎖的詳細(xì)內(nèi)容,更多關(guān)于MySQL鎖相關(guān)的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

  • MySql實(shí)現(xiàn)跨表查詢(xún)的方法詳解

    MySql實(shí)現(xiàn)跨表查詢(xún)的方法詳解

    本篇文章是對(duì)MySql實(shí)現(xiàn)跨表查詢(xún)的方法進(jìn)行了詳細(xì)的分析介紹,需要的朋友參考下
    2013-06-06
  • MySQL連接查詢(xún)你真的學(xué)會(huì)了嗎?

    MySQL連接查詢(xún)你真的學(xué)會(huì)了嗎?

    日常使用數(shù)據(jù)庫(kù)查詢(xún)語(yǔ)句時(shí),單表查詢(xún)嘗嘗不能滿足項(xiàng)目的業(yè)務(wù)需求,在項(xiàng)目開(kāi)發(fā)過(guò)程中,有很多需求都是要涉及到多表的連接查詢(xún),這篇文章主要給大家介紹了關(guān)于MySQL連接查詢(xún)的相關(guān)資料,需要的朋友可以參考下
    2021-06-06
  • 解決MySQL 8.0以上版本設(shè)置大小寫(xiě)不敏感的問(wèn)題

    解決MySQL 8.0以上版本設(shè)置大小寫(xiě)不敏感的問(wèn)題

    MySQL 8.0以上版本默認(rèn)區(qū)分大小寫(xiě),但在低版本(如5.7)中,可以通過(guò)在my.cnf配置文件的[mysqld]節(jié)下添加lower_case_table_names=1來(lái)設(shè)置大小寫(xiě)不敏感,本篇博客將介紹如何解決MySQL 8.0以上版本設(shè)置大小寫(xiě)不敏感的問(wèn)題,需要的朋友可以參考下
    2023-11-11
  • mysql 觸發(fā)器實(shí)現(xiàn)兩個(gè)表的數(shù)據(jù)同步

    mysql 觸發(fā)器實(shí)現(xiàn)兩個(gè)表的數(shù)據(jù)同步

    本文將介紹mysql 觸發(fā)器實(shí)現(xiàn)兩個(gè)表的數(shù)據(jù)同步,需要的朋友可以參考
    2012-11-11
  • 深入理解MySQL的行級(jí)鎖

    深入理解MySQL的行級(jí)鎖

    鎖是協(xié)調(diào)多進(jìn)程或線程并發(fā)訪問(wèn)資源的機(jī)制,對(duì)于數(shù)據(jù)庫(kù)而言,保證數(shù)據(jù)并發(fā)訪問(wèn)的一致性和有效性至關(guān)重要,本文主要介紹了MySQL的行級(jí)鎖,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-09-09
  • MySQL索引失效場(chǎng)景及解決方案

    MySQL索引失效場(chǎng)景及解決方案

    這篇文章主要介紹了MySQL索引失效場(chǎng)景及解決方案,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的朋友可以參考一下
    2022-07-07
  • MySQL避免插入重復(fù)記錄的方法

    MySQL避免插入重復(fù)記錄的方法

    這篇文章主要介紹了MySQL避免插入重復(fù)記錄的方法,需要的朋友可以參考下
    2023-10-10
  • mysql判斷字段是否存在的方法

    mysql判斷字段是否存在的方法

    mysql判斷字段是否存在的方法有很多,如使用desc命令、show columns 命令、describe 命令等等,感興趣的朋友可以參考下
    2014-01-01
  • MYSQL 數(shù)據(jù)庫(kù)導(dǎo)入導(dǎo)出命令

    MYSQL 數(shù)據(jù)庫(kù)導(dǎo)入導(dǎo)出命令

    在不同操作系統(tǒng)或MySQL版本情況下,直接拷貝文件的方法可能會(huì)有不兼容的情況發(fā)生。所以一般推薦用SQL腳本形式導(dǎo)入。下面分別介紹兩種方法。
    2010-11-11
  • 最新評(píng)論