欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

MySQL鎖類(lèi)型和加鎖原理是什么

這篇文章主要介紹了MySQL鎖類(lèi)型和加鎖原理是什么,具有一定借鑒價(jià)值,需要的朋友可以參考下。希望大家閱讀完這篇文章后大有收獲。下面讓小編帶著大家一起了解一下。

創(chuàng)新互聯(lián)從2013年成立,先為容城等服務(wù)建站,容城等地企業(yè),進(jìn)行企業(yè)商務(wù)咨詢(xún)服務(wù)。為容城企業(yè)網(wǎng)站制作PC+手機(jī)+微官網(wǎng)三網(wǎng)同步一站式服務(wù)解決您的所有建站問(wèn)題。

首先對(duì)mysql鎖進(jìn)行劃分:

  1. 按照鎖的粒度劃分:行鎖、表鎖、頁(yè)鎖
  2. 按照鎖的使用方式劃分:共享鎖、排它鎖(悲觀鎖的一種實(shí)現(xiàn))
  3. 還有兩種思想上的鎖:悲觀鎖、樂(lè)觀鎖。
  4. InnoDB中有幾種行級(jí)鎖類(lèi)型:Record Lock、Gap Lock、Next-key Lock
  5. Record Lock:在索引記錄上加鎖
  6. Gap Lock:間隙鎖
  7. Next-key Lock:Record Lock+Gap Lock

表鎖

表級(jí)鎖是 MySQL 鎖中粒度最大的一種鎖,表示當(dāng)前的操作對(duì)整張表加鎖,資源開(kāi)銷(xiāo)比行鎖少,不會(huì)出現(xiàn)死鎖的情況,但是發(fā)生鎖沖突的概率很大。被大部分的mysql引擎支持,MyISAM和InnoDB都支持表級(jí)鎖,但是InnoDB默認(rèn)的是行級(jí)鎖。

表鎖由 MySQL Server 實(shí)現(xiàn),一般在執(zhí)行 DDL 語(yǔ)句時(shí)會(huì)對(duì)整個(gè)表進(jìn)行加鎖,比如說(shuō) ALTER TABLE 等操作。在執(zhí)行 SQL 語(yǔ)句時(shí),也可以明確指定對(duì)某個(gè)表進(jìn)行加鎖。

表鎖使用的是一次性鎖技術(shù),也就是說(shuō),在會(huì)話(huà)開(kāi)始的地方使用 lock 命令將后續(xù)需要用到的表都加上鎖,在表釋放前,只能訪問(wèn)這些加鎖的表,不能訪問(wèn)其他表,直到最后通過(guò) unlock tables 釋放所有表鎖。

除了使用 unlock tables 顯示釋放鎖之外,會(huì)話(huà)持有其他表鎖時(shí)執(zhí)行l(wèi)ock table 語(yǔ)句會(huì)釋放會(huì)話(huà)之前持有的鎖;會(huì)話(huà)持有其他表鎖時(shí)執(zhí)行 start transaction 或者 begin 開(kāi)啟事務(wù)時(shí),也會(huì)釋放之前持有的鎖。

共享鎖用法

LOCK TABLE table_name [ AS alias_name ] READ復(fù)制代碼

排它鎖用法

LOCK TABLE table_name [AS alias_name][ LOW_PRIORITY ] WRITE復(fù)制代碼

解鎖用法

unlock tables;復(fù)制代碼

行鎖

行級(jí)鎖是Mysql中鎖定粒度最細(xì)的一種鎖,表示只針對(duì)當(dāng)前操作的行進(jìn)行加鎖。行級(jí)鎖能大大減少數(shù)據(jù)庫(kù)操作的沖突。其加鎖粒度最小,但加鎖的開(kāi)銷(xiāo)也最大。有可能會(huì)出現(xiàn)死鎖的情況。行級(jí)鎖按照使用方式分為共享鎖和排他鎖。

不同存儲(chǔ)引擎的行鎖實(shí)現(xiàn)不同,后續(xù)沒(méi)有特別說(shuō)明,則行鎖特指 InnoDB 實(shí)現(xiàn)的行鎖。

在了解 InnoDB 的加鎖原理前,需要對(duì)其存儲(chǔ)結(jié)構(gòu)有一定的了解。InnoDB 是聚簇索引,也就是 B+樹(shù)的葉節(jié)點(diǎn)既存儲(chǔ)了主鍵索引也存儲(chǔ)了數(shù)據(jù)行。而 InnoDB 的二級(jí)索引的葉節(jié)點(diǎn)存儲(chǔ)的則是主鍵值,所以通過(guò)二級(jí)索引查詢(xún)數(shù)據(jù)時(shí),還需要拿對(duì)應(yīng)的主鍵去聚簇索引中再次進(jìn)行查詢(xún)。關(guān)于MySQL索引的詳細(xì)知識(shí)可以查看《MySQL索引底層數(shù)據(jù)結(jié)構(gòu)與算法》。

下面以?xún)蓷l SQL 的執(zhí)行為例,講解一下 InnoDB 對(duì)于單行數(shù)據(jù)的加鎖原理。

update user set age = 10 where id = 49;
update user set age = 10 where name = 'Tom';復(fù)制代碼

第一條 SQL 使用主鍵索引來(lái)查詢(xún),則只需要在 id = 49 這個(gè)主鍵索引上加上寫(xiě)鎖;

第二條 SQL 則使用二級(jí)索引來(lái)查詢(xún),則首先在 name = Tom 這個(gè)索引上加寫(xiě)鎖,然后由于使用 InnoDB 二級(jí)索引還需再次根據(jù)主鍵索引查詢(xún),所以還需要在 id = 49 這個(gè)主鍵索引上加寫(xiě)鎖,如上圖所示。

也就是說(shuō)使用主鍵索引需要加一把鎖,使用二級(jí)索引需要在二級(jí)索引和主鍵索引上各加一把鎖。

根據(jù)索引對(duì)單行數(shù)據(jù)進(jìn)行更新的加鎖原理了解了,那如果更新操作涉及多個(gè)行呢,比如下面 SQL 的執(zhí)行場(chǎng)景。

update user set age = 10 where id > 49;復(fù)制代碼

這種場(chǎng)景下的鎖的釋放較為復(fù)雜,有多種的優(yōu)化方式,我對(duì)這塊暫時(shí)還沒(méi)有了解,還請(qǐng)知道的小伙伴在下方留言解釋。

頁(yè)鎖

頁(yè)級(jí)鎖是MySQL中鎖定粒度介于行級(jí)鎖和表級(jí)鎖中間的一種鎖。表級(jí)鎖速度快,但沖突多,行級(jí)沖突少,但速度慢。所以取了折衷的頁(yè)級(jí),一次鎖定相鄰的一組記錄。BDB支持頁(yè)級(jí)鎖。

共享鎖/排他鎖

共享鎖(Share Lock)

共享鎖又稱(chēng)讀鎖,是讀取操作創(chuàng)建的鎖。其他用戶(hù)可以并發(fā)讀取數(shù)據(jù),但任何事務(wù)都不能對(duì)數(shù)據(jù)進(jìn)行修改(獲取數(shù)據(jù)上的排他鎖),直到已釋放所有共享鎖。

如果事務(wù)T對(duì)數(shù)據(jù)A加上共享鎖后,則其他事務(wù)只能對(duì)A再加共享鎖,不能加排他鎖。獲準(zhǔn)共享鎖的事務(wù)只能讀數(shù)據(jù),不能修改數(shù)據(jù)。

用法

SELECT ... LOCK IN SHARE MODE;

在查詢(xún)語(yǔ)句后面增加LOCK IN SHARE MODE,Mysql會(huì)對(duì)查詢(xún)結(jié)果中的每行都加共享鎖,當(dāng)沒(méi)有其他線程對(duì)查詢(xún)結(jié)果集中的任何一行使用排他鎖時(shí),可以成功申請(qǐng)共享鎖,否則會(huì)被阻塞。其他線程也可以讀取使用了共享鎖的表,而且這些線程讀取的是同一個(gè)版本的數(shù)據(jù)。

排他鎖(eXclusive Lock)

排他鎖又稱(chēng)寫(xiě)鎖,如果事務(wù)T對(duì)數(shù)據(jù)A加上排他鎖后,則其他事務(wù)不能再對(duì)A加任任何類(lèi)型的封鎖。獲準(zhǔn)排他鎖的事務(wù)既能讀數(shù)據(jù),又能修改數(shù)據(jù)。

用法

SELECT ... FOR UPDATE;

在查詢(xún)語(yǔ)句后面增加FOR UPDATE,Mysql會(huì)對(duì)查詢(xún)結(jié)果中的每行都加排他鎖,當(dāng)沒(méi)有其他線程對(duì)查詢(xún)結(jié)果集中的任何一行使用排他鎖時(shí),可以成功申請(qǐng)排他鎖,否則會(huì)被阻塞。

樂(lè)觀鎖和悲觀鎖

在數(shù)據(jù)庫(kù)的鎖機(jī)制中介紹過(guò),數(shù)據(jù)庫(kù)管理系統(tǒng)(DBMS)中的并發(fā)控制的任務(wù)是確保在多個(gè)事務(wù)同時(shí)存取數(shù)據(jù)庫(kù)中同一數(shù)據(jù)時(shí)不破壞事務(wù)的隔離性和統(tǒng)一性以及數(shù)據(jù)庫(kù)的統(tǒng)一性。

樂(lè)觀并發(fā)控制(樂(lè)觀鎖)和悲觀并發(fā)控制(悲觀鎖)是并發(fā)控制主要采用的技術(shù)手段。

無(wú)論是悲觀鎖還是樂(lè)觀鎖,都是人們定義出來(lái)的概念,可以認(rèn)為是一種思想。其實(shí)不僅僅是關(guān)系型數(shù)據(jù)庫(kù)系統(tǒng)中有樂(lè)觀鎖和悲觀鎖的概念,像memcache、hibernate、tair等都有類(lèi)似的概念。

針對(duì)于不同的業(yè)務(wù)場(chǎng)景,應(yīng)該選用不同的并發(fā)控制方式。所以,不要把樂(lè)觀并發(fā)控制和悲觀并發(fā)控制狹義的理解為DBMS中的概念,更不要把他們和數(shù)據(jù)中提供的鎖機(jī)制(行鎖、表鎖、排他鎖、共享鎖)混為一談。其實(shí),在DBMS中,悲觀鎖正是利用數(shù)據(jù)庫(kù)本身提供的鎖機(jī)制來(lái)實(shí)現(xiàn)的。

悲觀鎖

在關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)里,悲觀并發(fā)控制(又名“悲觀鎖”,Pessimistic Concurrency Control,縮寫(xiě)“PCC”)是一種并發(fā)控制的方法。它可以阻止一個(gè)事務(wù)以影響其他用戶(hù)的方式來(lái)修改數(shù)據(jù)。如果一個(gè)事務(wù)執(zhí)行的操作對(duì)某行數(shù)據(jù)應(yīng)用了鎖,那只有當(dāng)這個(gè)事務(wù)把鎖釋放,其他事務(wù)才能夠執(zhí)行與該鎖沖突的操作。悲觀并發(fā)控制主要用于數(shù)據(jù)爭(zhēng)用激烈的環(huán)境,以及發(fā)生并發(fā)沖突時(shí)使用鎖保護(hù)數(shù)據(jù)的成本要低于回滾事務(wù)的成本的環(huán)境中。

悲觀鎖,正如其名,它指的是對(duì)數(shù)據(jù)被外界(包括本系統(tǒng)當(dāng)前的其他事務(wù),以及來(lái)自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度(悲觀),因此,在整個(gè)數(shù)據(jù)處理過(guò)程中,將數(shù)據(jù)處于鎖定狀態(tài)。 悲觀鎖的實(shí)現(xiàn),往往依靠數(shù)據(jù)庫(kù)提供的鎖機(jī)制 (也只有數(shù)據(jù)庫(kù)層提供的鎖機(jī)制才能真正保證數(shù)據(jù)訪問(wèn)的排他性,否則,即使在本系統(tǒng)中實(shí)現(xiàn)了加鎖機(jī)制,也無(wú)法保證外部系統(tǒng)不會(huì)修改數(shù)據(jù))

悲觀鎖的具體流程
  • 在對(duì)任意記錄進(jìn)行修改前,先嘗試為該記錄加上排他鎖(exclusive locking);
  • 如果加鎖失敗,說(shuō)明該記錄正在被修改,那么當(dāng)前查詢(xún)可能要等待或者拋出異常。 具體響應(yīng)方式由開(kāi)發(fā)者根據(jù)實(shí)際需要決定;
  • 如果成功加鎖,那么就可以對(duì)記錄做修改,事務(wù)完成后就會(huì)解鎖了。
  • 其間如果有其他對(duì)該記錄做修改或加排他鎖的操作,都會(huì)等待我們解鎖或直接拋出異常。
悲觀鎖的優(yōu)點(diǎn)和不足

悲觀鎖實(shí)際上是采取了“先取鎖在訪問(wèn)”的策略,為數(shù)據(jù)的處理安全提供了保證,但是在效率方面,由于額外的加鎖機(jī)制產(chǎn)生了額外的開(kāi)銷(xiāo),并且增加了死鎖的機(jī)會(huì)。并且降低了并發(fā)性;當(dāng)一個(gè)事物所以一行數(shù)據(jù)的時(shí)候,其他事物必須等待該事務(wù)提交之后,才能操作這行數(shù)據(jù)。

樂(lè)觀鎖

在關(guān)系數(shù)據(jù)庫(kù)管理系統(tǒng)里,樂(lè)觀并發(fā)控制(又名“樂(lè)觀鎖”,Optimistic Concurrency Control,縮寫(xiě)“OCC”)是一種并發(fā)控制的方法。它假設(shè)多用戶(hù)并發(fā)的事務(wù)在處理時(shí)不會(huì)彼此互相影響,各事務(wù)能夠在不產(chǎn)生鎖的情況下處理各自影響的那部分?jǐn)?shù)據(jù)。在提交數(shù)據(jù)更新之前,每個(gè)事務(wù)會(huì)先檢查在該事務(wù)讀取數(shù)據(jù)后,有沒(méi)有其他事務(wù)又修改了該數(shù)據(jù)。如果其他事務(wù)有更新的話(huà),正在提交的事務(wù)會(huì)進(jìn)行回滾。

樂(lè)觀鎖( Optimistic Locking ) 相對(duì)悲觀鎖而言,樂(lè)觀鎖假設(shè)認(rèn)為數(shù)據(jù)一般情況下不會(huì)造成沖突,所以在數(shù)據(jù)進(jìn)行提交更新的時(shí)候,才會(huì)正式對(duì)數(shù)據(jù)的沖突與否進(jìn)行檢測(cè),如果發(fā)現(xiàn)沖突了,則讓返回用戶(hù)錯(cuò)誤的信息,讓用戶(hù)決定如何去做。

相對(duì)于悲觀鎖,在對(duì)數(shù)據(jù)庫(kù)進(jìn)行處理的時(shí)候,樂(lè)觀鎖并不會(huì)使用數(shù)據(jù)庫(kù)提供的鎖機(jī)制。一般的實(shí)現(xiàn)樂(lè)觀鎖的方式就是記錄數(shù)據(jù)版本。

數(shù)據(jù)版本,為數(shù)據(jù)增加的一個(gè)版本標(biāo)識(shí)。當(dāng)讀取數(shù)據(jù)時(shí),將版本標(biāo)識(shí)的值一同讀出,數(shù)據(jù)每更新一次,同時(shí)對(duì)版本標(biāo)識(shí)進(jìn)行更新。當(dāng)我們提交更新的時(shí)候,判斷數(shù)據(jù)庫(kù)表對(duì)應(yīng)記錄的當(dāng)前版本信息與第一次取出來(lái)的版本標(biāo)識(shí)進(jìn)行比對(duì),如果數(shù)據(jù)庫(kù)表當(dāng)前版本號(hào)與第一次取出來(lái)的版本標(biāo)識(shí)值相等,則予以更新,否則認(rèn)為是過(guò)期數(shù)據(jù)。

樂(lè)觀鎖的優(yōu)點(diǎn)和不足

樂(lè)觀并發(fā)控制相信事務(wù)之間的數(shù)據(jù)競(jìng)爭(zhēng)(data race)的概率是比較小的,因此盡可能直接做下去,直到提交的時(shí)候才去鎖定,所以不會(huì)產(chǎn)生任何鎖和死鎖。但如果直接簡(jiǎn)單這么做,還是有可能會(huì)遇到不可預(yù)期的結(jié)果,例如兩個(gè)事務(wù)都讀取了數(shù)據(jù)庫(kù)的某一行,經(jīng)過(guò)修改以后寫(xiě)回?cái)?shù)據(jù)庫(kù),這時(shí)就遇到了問(wèn)題。

意向共享鎖/意向排他鎖

由于表鎖和行鎖雖然鎖定范圍不同,但是會(huì)相互沖突。所以當(dāng)你要加表鎖時(shí),勢(shì)必要先遍歷該表的所有記錄,判斷是否加有排他鎖。這種遍歷檢查的方式顯然是一種低效的方式,MySQL 引入了意向鎖,來(lái)檢測(cè)表鎖和行鎖的沖突。

意向鎖也是表級(jí)鎖,也可分為讀意向鎖(IS 鎖)和寫(xiě)意向鎖(IX 鎖)。當(dāng)事務(wù)要在記錄上加上讀鎖或?qū)戞i時(shí),要首先在表上加上意向鎖。這樣判斷表中是否有記錄加鎖就很簡(jiǎn)單了,只要看下表上是否有意向鎖就行了。

意向鎖之間是不會(huì)產(chǎn)生沖突的,也不和 AUTO_INC 表鎖沖突,它只會(huì)阻塞表級(jí)讀鎖或表級(jí)寫(xiě)鎖,另外,意向鎖也不會(huì)和行鎖沖突,行鎖只會(huì)和行鎖沖突。

意向鎖是InnoDB自動(dòng)加的,不需要用戶(hù)干預(yù)。

對(duì)于insert、update、delete,InnoDB會(huì)自動(dòng)給涉及的數(shù)據(jù)加排他鎖(X);

對(duì)于一般的Select語(yǔ)句,InnoDB不會(huì)加任何鎖,事務(wù)可以通過(guò)以下語(yǔ)句給顯示加共享鎖或排他鎖。

意向共享鎖(Intention Shared Lock)

意向共享鎖(IS):表示事務(wù)準(zhǔn)備給數(shù)據(jù)行加入共享鎖,也就是說(shuō)一個(gè)數(shù)據(jù)行加共享鎖前必須先取得該表的IS鎖

意向排他鎖(Exclusive Lock)

意向排他鎖(IX):類(lèi)似上面,表示事務(wù)準(zhǔn)備給數(shù)據(jù)行加入排他鎖,說(shuō)明事務(wù)在一個(gè)數(shù)據(jù)行加排他鎖前必須先取得該表的IX鎖。

記錄鎖(Record Lock)

記錄鎖是最簡(jiǎn)單的行鎖,并沒(méi)有什么好說(shuō)的。上邊描述 InnoDB 加鎖原理中的鎖就是記錄鎖,只鎖住 id = 49 或者 name = 'Tom' 這一條記錄。

當(dāng) SQL 語(yǔ)句無(wú)法使用索引時(shí),會(huì)進(jìn)行全表掃描,這個(gè)時(shí)候 MySQL 會(huì)給整張表的所有數(shù)據(jù)行加記錄鎖,再由 MySQL Server 層進(jìn)行過(guò)濾。但是,在 MySQL Server 層進(jìn)行過(guò)濾的時(shí)候,如果發(fā)現(xiàn)不滿(mǎn)足 WHERE 條件,會(huì)釋放對(duì)應(yīng)記錄的鎖。這樣做,保證了最后只會(huì)持有滿(mǎn)足條件記錄上的鎖,但是每條記錄的加鎖操作還是不能省略的。

所以更新操作必須要根據(jù)索引進(jìn)行操作,沒(méi)有索引時(shí),不僅會(huì)消耗大量的鎖資源,增加數(shù)據(jù)庫(kù)的開(kāi)銷(xiāo),還會(huì)極大的降低了數(shù)據(jù)庫(kù)的并發(fā)性能。

間隙鎖(Gap Lock)

當(dāng)我們使用范圍條件而不是相等條件檢索數(shù)據(jù),并請(qǐng)求共享或排他鎖時(shí),InnoDB會(huì)給符合條件的已有數(shù)據(jù)記錄的索引項(xiàng)加鎖;對(duì)于鍵值在條件范圍內(nèi)但并不存在的記錄,InnoDB 也會(huì)對(duì)這個(gè)“間隙”加鎖,這種鎖機(jī)制就是所謂的間隙鎖。

間隙鎖是鎖索引記錄中的間隔,或者第一條索引記錄之前的范圍,又或者最后一條索引記錄之后的范圍。

間隙鎖在 InnoDB 的唯一作用就是防止其它事務(wù)的插入操作,以此來(lái)達(dá)到防止幻讀的發(fā)生,所以間隙鎖不分什么共享鎖與排他鎖。

要禁止間隙鎖,可以把隔離級(jí)別降為讀已提交,或者開(kāi)啟參數(shù) innodb_locks_unsafe_for_binlog

 show variables like 'innodb_locks_unsafe_for_binlog';復(fù)制代碼

innodb_locks_unsafe_for_binlog:默認(rèn)

值為OFF,即啟用間隙鎖。因?yàn)榇藚?shù)是只讀模式,如果想要禁用間隙鎖,需要修改 my.cnf(windows是my.ini) 重新啟動(dòng)才行。

# 在 my.cnf 里面的[mysqld]添加
[mysqld]
innodb_locks_unsafe_for_binlog = 1復(fù)制代碼

案例1:唯一索引的間隙鎖

測(cè)試環(huán)境

MySQL5.7,InnoDB,默認(rèn)的隔離級(jí)別(RR)

示例表

CREATE TABLE `my_gap` (  `id` int(1) NOT NULL AUTO_INCREMENT,  `name` varchar(8) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;INSERT INTO `my_gap` VALUES ('1', '張三');INSERT INTO `my_gap` VALUES ('5', '李四');INSERT INTO `my_gap` VALUES ('7', '王五');INSERT INTO `my_gap` VALUES ('11', '趙六');復(fù)制代碼

在進(jìn)行測(cè)試之前,我們先看看 my_gap 表中存在的隱藏間隙:

  1. (-infinity, 1]
  2. (1, 5]
  3. (5, 7]
  4. (7, 11]
  5. (11, +infinity]
只使用記錄鎖(行鎖),不會(huì)產(chǎn)生間隙鎖
/* 開(kāi)啟事務(wù)1 */BEGIN;/* 查詢(xún) id = 5 的數(shù)據(jù)并加記錄鎖 */SELECT * FROM `my_gap` WHERE `id` = 5 FOR UPDATE;/* 延遲30秒執(zhí)行,防止鎖釋放 */SELECT SLEEP(30);

# 注意:以下的語(yǔ)句不是放在一個(gè)事務(wù)中執(zhí)行,而是分開(kāi)多次執(zhí)行,每次事務(wù)中只有一條添加語(yǔ)句/* 事務(wù)2插入一條 name = '杰倫' 的數(shù)據(jù) */INSERT INTO `my_gap` (`id`, `name`) VALUES (4, '杰倫'); # 正常執(zhí)行/* 事務(wù)3插入一條 name = '學(xué)友' 的數(shù)據(jù) */INSERT INTO `my_gap` (`id`, `name`) VALUES (8, '學(xué)友'); # 正常執(zhí)行/* 提交事務(wù)1,釋放事務(wù)1的鎖 */COMMIT;復(fù)制代碼

上述案例,由于主鍵是唯一索引,而且只使用一個(gè)索引查詢(xún),并且只鎖定了一條記錄,所以只會(huì)對(duì) id = 5 的數(shù)據(jù)加上記錄鎖(行鎖),而不會(huì)產(chǎn)生間隙鎖。

產(chǎn)生間隙鎖

恢復(fù)初始化的4條記錄,繼續(xù)在 id 唯一索引列上做以下測(cè)試:

/* 開(kāi)啟事務(wù)1 */BEGIN;/* 查詢(xún) id 在 7 - 11 范圍的數(shù)據(jù)并加記錄鎖 */SELECT * FROM `my_gap` WHERE `id` BETWEEN 5 AND 7 FOR UPDATE;/* 延遲30秒執(zhí)行,防止鎖釋放 */SELECT SLEEP(30);

# 注意:以下的語(yǔ)句不是放在一個(gè)事務(wù)中執(zhí)行,而是分開(kāi)多次執(zhí)行,每次事務(wù)中只有一條添加語(yǔ)句/* 事務(wù)2插入一條 id = 3,name = '思聰3' 的數(shù)據(jù) */INSERT INTO `my_gap` (`id`, `name`) VALUES (3, '思聰3'); # 正常執(zhí)行/* 事務(wù)3插入一條 id = 4,name = '思聰4' 的數(shù)據(jù) */INSERT INTO `my_gap` (`id`, `name`) VALUES (4, '思聰4'); # 正常執(zhí)行/* 事務(wù)4插入一條 id = 6,name = '思聰6' 的數(shù)據(jù) */INSERT INTO `my_gap` (`id`, `name`) VALUES (6, '思聰6'); # 阻塞/* 事務(wù)5插入一條 id = 8, name = '思聰8' 的數(shù)據(jù) */INSERT INTO `my_gap` (`id`, `name`) VALUES (8, '思聰8'); # 阻塞/* 事務(wù)6插入一條 id = 9, name = '思聰9' 的數(shù)據(jù) */INSERT INTO `my_gap` (`id`, `name`) VALUES (9, '思聰9'); # 阻塞/* 事務(wù)7插入一條 id = 11, name = '思聰11' 的數(shù)據(jù) */INSERT INTO `my_gap` (`id`, `name`) VALUES (11, '思聰11'); # 阻塞/* 事務(wù)8插入一條 id = 12, name = '思聰12' 的數(shù)據(jù) */INSERT INTO `my_gap` (`id`, `name`) VALUES (12, '思聰12'); # 正常執(zhí)行/* 提交事務(wù)1,釋放事務(wù)1的鎖 */COMMIT;復(fù)制代碼

從上面可以看到,(5,7]、(7,11] 這兩個(gè)區(qū)間,都不可插入數(shù)據(jù),其它區(qū)間,都可以正常插入數(shù)據(jù)。所以可以得出結(jié)論:當(dāng)我們給(5,7] 這個(gè)區(qū)間加鎖的時(shí)候,會(huì)鎖住(5,7]、(7,11] 這兩個(gè)區(qū)間

恢復(fù)初始化的4條記錄,我們?cè)賮?lái)測(cè)試如果鎖住不存在的數(shù)據(jù)時(shí),會(huì)如何?

/* 開(kāi)啟事務(wù)1 */BEGIN;/* 查詢(xún) id = 3 這一條不存在的數(shù)據(jù)并加記錄鎖 */SELECT * FROM `my_gap` WHERE `id` = 3 FOR UPDATE;/* 延遲30秒執(zhí)行,防止鎖釋放 */SELECT SLEEP(30);

# 注意:以下的語(yǔ)句不是放在一個(gè)事務(wù)中執(zhí)行,而是分開(kāi)多次執(zhí)行,每次事務(wù)中只有一條添加語(yǔ)句/* 事務(wù)2插入一條 id = 3,name = '小張' 的數(shù)據(jù) */INSERT INTO `my_gap` (`id`, `name`) VALUES (2, '小張'); # 阻塞/* 事務(wù)3插入一條 id = 4,name = '小白' 的數(shù)據(jù) */INSERT INTO `my_gap` (`id`, `name`) VALUES (4, '小白'); # 阻塞/* 事務(wù)4插入一條 id = 6,name = '小東' 的數(shù)據(jù) */INSERT INTO `my_gap` (`id`, `name`) VALUES (6, '小東'); # 正常執(zhí)行/* 事務(wù)5插入一條 id = 8, name = '大羅' 的數(shù)據(jù) */INSERT INTO `my_gap` (`id`, `name`) VALUES (8, '大羅'); # 正常執(zhí)行/* 提交事務(wù)1,釋放事務(wù)1的鎖 */COMMIT;復(fù)制代碼

從上面可以看出,指定查詢(xún)某一條記錄時(shí),如果這條記錄不存在,會(huì)產(chǎn)生間隙鎖。

結(jié)論
  1. 對(duì)于指定查詢(xún)某一條記錄的加鎖語(yǔ)句,如果該記錄不存在,會(huì)產(chǎn)生記錄鎖(行鎖)和間隙鎖,如果記錄存在,則只會(huì)產(chǎn)生記錄鎖(行鎖);
  2. 對(duì)于查找某一范圍內(nèi)的查詢(xún)語(yǔ)句,會(huì)產(chǎn)生間隙鎖。

案例2:普通索引的間隙鎖

示例表:id 是主鍵,在 number 上,建立了一個(gè)普通索引。

# 注意:number 不是唯一值CREATE TABLE `my_gap1` (  `id` int(1) NOT NULL AUTO_INCREMENT,  `number` int(1) NOT NULL COMMENT '數(shù)字',
  PRIMARY KEY (`id`),  KEY `number` (`number`) USING BTREE
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;INSERT INTO `my_gap1` VALUES (1, 1);INSERT INTO `my_gap1` VALUES (5, 3);INSERT INTO `my_gap1` VALUES (7, 8);INSERT INTO `my_gap1` VALUES (11, 12);復(fù)制代碼

在進(jìn)行測(cè)試之前,我們先來(lái)看看 my_gap1 表中 number 索引存在的隱藏間隙:

  1. (-infinity, 1]
  2. (1, 3]
  3. (3, 8]
  4. (8, 12]
  5. (12, +infinity]
測(cè)試1

我們執(zhí)行以下的事務(wù)(事務(wù)1最后提交),分別執(zhí)行下面的語(yǔ)句:

/* 開(kāi)啟事務(wù)1 */BEGIN;/* 查詢(xún) number = 3 的數(shù)據(jù)并加記錄鎖 */SELECT * FROM `my_gap1` WHERE `number` = 3 FOR UPDATE;/* 延遲30秒執(zhí)行,防止鎖釋放 */SELECT SLEEP(30);

# 注意:以下的語(yǔ)句不是放在一個(gè)事務(wù)中執(zhí)行,而是分開(kāi)多次執(zhí)行,每次事務(wù)中只有一條添加語(yǔ)句/* 事務(wù)2插入一條 number = 0 的數(shù)據(jù) */INSERT INTO `my_gap1` (`number`) VALUES (0); # 正常執(zhí)行/* 事務(wù)3插入一條 number = 1 的數(shù)據(jù) */INSERT INTO `my_gap1` (`number`) VALUES (1); # 被阻塞/* 事務(wù)4插入一條 number = 2 的數(shù)據(jù) */INSERT INTO `my_gap1` (`number`) VALUES (2); # 被阻塞/* 事務(wù)5插入一條 number = 4 的數(shù)據(jù) */INSERT INTO `my_gap1` (`number`) VALUES (4); # 被阻塞/* 事務(wù)6插入一條 number = 8 的數(shù)據(jù) */INSERT INTO `my_gap1` (`number`) VALUES (8); # 正常執(zhí)行/* 事務(wù)7插入一條 number = 9 的數(shù)據(jù) */INSERT INTO `my_gap1` (`number`) VALUES (9); # 正常執(zhí)行/* 事務(wù)8插入一條 number = 10 的數(shù)據(jù) */INSERT INTO `my_gap1` (`number`) VALUES (10); # 正常執(zhí)行/* 提交事務(wù)1 */COMMIT;復(fù)制代碼

我們會(huì)發(fā)現(xiàn)有些語(yǔ)句可以正常執(zhí)行,有些語(yǔ)句被阻塞來(lái)。查看表中的數(shù)據(jù):

這里可以看到,number(1,8) 的間隙中,插入語(yǔ)句都被阻塞來(lái),而不在這個(gè)范圍內(nèi)的語(yǔ)句,正常執(zhí)行,這就是因?yàn)橛虚g隙鎖的原因。

測(cè)試2

我們?cè)龠M(jìn)行以下測(cè)試,這里將數(shù)據(jù)還原成初始化那樣

/* 開(kāi)啟事務(wù)1 */BEGIN;/* 查詢(xún) number = 3 的數(shù)據(jù)并加記錄鎖 */SELECT * FROM `my_gap1` WHERE `number` = 3 FOR UPDATE;/* 延遲30秒執(zhí)行,防止鎖釋放 */SELECT SLEEP(30);/* 事務(wù)1插入一條 id = 2, number = 1 的數(shù)據(jù) */INSERT INTO `my_gap1` (`id`, `number`) VALUES (2, 1); # 阻塞/* 事務(wù)2插入一條 id = 3, number = 2 的數(shù)據(jù) */INSERT INTO `my_gap1` (`id`, `number`) VALUES (3, 2); # 阻塞/* 事務(wù)3插入一條 id = 6, number = 8 的數(shù)據(jù) */INSERT INTO `my_gap1` (`id`, `number`) VALUES (6, 8); # 阻塞/* 事務(wù)4插入一條 id = 8, number = 8 的數(shù)據(jù) */INSERT INTO `my_gap1` (`id`, `number`) VALUES (8, 8); # 正常執(zhí)行/* 事務(wù)5插入一條 id = 9, number = 9 的數(shù)據(jù) */INSERT INTO `my_gap1` (`id`, `number`) VALUES (9, 9); # 正常執(zhí)行/* 事務(wù)6插入一條 id = 10, number = 12 的數(shù)據(jù) */INSERT INTO `my_gap1` (`id`, `number`) VALUES (10, 12); # 正常執(zhí)行/* 事務(wù)7修改 id = 11, number = 12 的數(shù)據(jù) */UPDATE `my_gap1` SET `number` = 5 WHERE `id` = 11 AND `number` = 12; # 阻塞/* 提交事務(wù)1 */COMMIT;復(fù)制代碼

查看表中的數(shù)據(jù);

這里有一個(gè)奇怪的現(xiàn)象:

  • 事務(wù)3 添加 id = 6,number = 8 的數(shù)據(jù),阻塞了;
  • 事務(wù)4 添加 id = 8,number = 8 的數(shù)據(jù),正常執(zhí)行了;
  • 事務(wù)7 將 id = 11,number = 12 的數(shù)據(jù)修改為 id = 11, number = 5 的操作,給阻塞了。

這是為什么?我們來(lái)看看下面的圖:

從圖中庫(kù)看出,當(dāng) number 相同時(shí),會(huì)根據(jù)主鍵 id 來(lái)排序

  1. 事務(wù) 3 添加的 id = 6,number = 8,這條數(shù)據(jù)是在 (3,8) 的區(qū)間里邊,所以會(huì)阻塞;
  2. 事務(wù) 4 添加的 id = 8,number = 8,這條數(shù)據(jù)實(shí)在 (8,12) 區(qū)間里邊,所以不會(huì)阻塞;
  3. 事務(wù) 7 的修改語(yǔ)句相當(dāng)于 在 (3,8) 的區(qū)間里邊插入一條數(shù)據(jù),所以也被阻塞了。
結(jié)論
  1. 在普通索引列上,不管是何種查詢(xún),只要加鎖,都會(huì)產(chǎn)生間隙鎖,這跟唯一索引不一樣
  2. 在普通索引跟唯一索引中,數(shù)據(jù)間隙的分析,數(shù)據(jù)行是優(yōu)先根據(jù)普通普通索引排序,再根據(jù)唯一索引排序。

臨鍵鎖(Next-key Locks)

臨鍵鎖,是記錄鎖(行鎖)與間隙鎖的組合,它的鎖范圍,即包含索引記錄,又包含索引區(qū)間。它指的是加在某條記錄以及這條記錄前面間隙上的鎖。假設(shè)一個(gè)索引包含 15、18、20 ,30,49,50 這幾個(gè)值,可能的 Next-key 鎖如下:

(-∞, 15],(15, 18],(18, 20],(20, 30],(30, 49],(49, 50],(50, +∞)復(fù)制代碼

通常我們都用這種左開(kāi)右閉區(qū)間來(lái)表示 Next-key 鎖,其中,圓括號(hào)表示不包含該記錄,方括號(hào)表示包含該記錄。前面四個(gè)都是 Next-key 鎖,最后一個(gè)為間隙鎖。和間隙鎖一樣,在 RC 隔離級(jí)別下沒(méi)有 Next-key 鎖,只有 RR 隔離級(jí)別才有。還是之前的例子,如果 id 不是主鍵,而是二級(jí)索引,且不是唯一索引,那么這個(gè) SQL 在 RR 隔離級(jí)別下就會(huì)加如下的 Next-key 鎖 (30, 49](49, 50)

此時(shí)如果插入一條 id = 31 的記錄將會(huì)阻塞住。之所以要把 id = 49 前后的間隙都鎖住,仍然是為了解決幻讀問(wèn)題,因?yàn)?id 是非唯一索引,所以 id = 49 可能會(huì)有多條記錄,為了防止再插入一條 id = 49 的記錄。

注意:臨鍵鎖的主要目的,也是為了避免幻讀(Phantom Read)。如果把事務(wù)隔離級(jí)別降級(jí)為 RC,臨鍵鎖則也會(huì)失效。

插入意向鎖(Insert Intention Locks)

插入意向鎖是一種特殊的間隙鎖(簡(jiǎn)稱(chēng)II GAP)表示插入的意向,只有在 INSERT 的時(shí)候才會(huì)有這個(gè)鎖。注意,這個(gè)鎖雖然也叫意向鎖,但是和上面介紹的表級(jí)意向鎖是兩個(gè)完全不同的概念,不要搞混了。

插入意向鎖和插入意向鎖之間互不沖突,所以可以在同一個(gè)間隙中有多個(gè)事務(wù)同時(shí)插入不同索引的記錄。譬如在例子中,id = 30 和 id = 49 之間如果有兩個(gè)事務(wù)要同時(shí)分別插入 id = 32 和 id = 33 是沒(méi)問(wèn)題的,雖然兩個(gè)事務(wù)都會(huì)在 id = 30 和 id = 50 之間加上插入意向鎖,但是不會(huì)沖突。

插入意向鎖只會(huì)和間隙鎖或 Next-key 鎖沖突,正如上面所說(shuō),間隙鎖唯一的作用就是防止其他事務(wù)插入記錄造成幻讀,正是由于在執(zhí)行 INSERT 語(yǔ)句時(shí)需要加插入意向鎖,而插入意向鎖和間隙鎖沖突,從而阻止了插入操作的執(zhí)行。

插入意向鎖的作用:

  1. 為來(lái)喚起等待。由于該間隙已經(jīng)有鎖,插入時(shí)必須阻塞,插入意向鎖的作用具有阻塞功能;
  2. 插入意向鎖是一種特殊的間隙鎖,既然是一種間隙鎖,為什么不直接使用間隙鎖?間隙鎖直接不相互排斥。不可以阻塞即喚起等待,會(huì)造成幻讀。
  3. 為什么不實(shí)用記錄鎖(行鎖)或 臨鍵鎖?申請(qǐng)了記錄鎖或臨鍵鎖,臨鍵鎖之間可能相互排斥,即影響 insert 的并發(fā)性。

自增鎖(Auto-inc Locks)

AUTO_INC 鎖又叫自增鎖(一般簡(jiǎn)寫(xiě)成 AI 鎖),是一種表鎖,當(dāng)表中有自增列(AUTO_INCREMENT)時(shí)出現(xiàn)。當(dāng)插入表中有自增列時(shí),數(shù)據(jù)庫(kù)需要自動(dòng)生成自增值,它會(huì)先為該表加 AUTO_INC 表鎖,阻塞其他事務(wù)的插入操作,這樣保證生成的自增值肯定是唯一的。AUTO_INC 鎖具有如下特點(diǎn):

  • AUTO_INC 鎖互不兼容,也就是說(shuō)同一張表同時(shí)只允許有一個(gè)自增鎖;
  • 自增值一旦分配了就會(huì) +1,如果事務(wù)回滾,自增值也不會(huì)減回去,所以自增值可能會(huì)出現(xiàn)中斷的情況。

自增操作

使用AUTO_INCREMENT 函數(shù)實(shí)現(xiàn)自增操作,自增幅度通過(guò) auto_increment_offsetauto_increment_increment這2個(gè)參數(shù)進(jìn)行控制:

  • auto_increment_offset 表示起始數(shù)字
  • auto_increment_increment 表示調(diào)動(dòng)幅度(即每次增加n個(gè)數(shù)字,2就代表每次+2)

通過(guò)使用last_insert_id()函數(shù)可以獲得最后一個(gè)插入的數(shù)字

select last_insert_id();復(fù)制代碼

自增鎖

首先insert大致上可以分成三類(lèi):

  1. simple insert 如insert into t(name) values('test')
  2. bulk insert 如load data | insert into ... select .... from ....
  3. mixed insert 如insert into t(id,name) values(1,'a'),(null,'b'),(5,'c');

如果存在自增字段,MySQL 會(huì)維護(hù)一個(gè)自增鎖,和自增鎖相關(guān)的一個(gè)參數(shù)為(5.1.22 版本后加入) innodb_autoinc_lock_mode ,可以設(shè)定 3 值:

  • 0 :traditonal (每次都會(huì)產(chǎn)生表鎖)
  • 1 :consecutive(會(huì)產(chǎn)生一個(gè)輕量鎖,simple insert 會(huì)獲得批量的鎖,保證連續(xù)插入)
  • 2 :interleaved (不會(huì)鎖表,來(lái)一個(gè)處理一個(gè),并發(fā)最高)

    MyISam引擎均為 traditonal,每次均會(huì)進(jìn)行表鎖。但是InnoDB引擎會(huì)視參數(shù)不同產(chǎn)生不同的鎖,默認(rèn)為 1:consecutive。

 show variables like 'innodb_autoinc_lock_mode';復(fù)制代碼
traditonal

innodb_autoinc_lock_mode 為 0 時(shí),也就是 traditional 級(jí)別。該自增鎖時(shí)表鎖級(jí)別,且必須等待當(dāng)前 SQL 執(zhí)行完畢后或者回滾才會(huì)釋放,在高并發(fā)的情況下可想而知自增鎖競(jìng)爭(zhēng)時(shí)比較大的。

  • 它提供來(lái)一個(gè)向后兼容的能力
  • 在這一模式下,所有的 insert 語(yǔ)句(“insert like”)都要在語(yǔ)句開(kāi)始的時(shí)候得到一個(gè)表級(jí)的 auto_inc 鎖,在語(yǔ)句結(jié)束的時(shí)候才釋放這把鎖。注意,這里說(shuō)的是語(yǔ)句級(jí)而不是事務(wù)級(jí)的,一個(gè)事務(wù)可能包含有一個(gè)或多個(gè)語(yǔ)句;
  • 它能保證值分配的可預(yù)見(jiàn)性、可連續(xù)性、可重復(fù)性,這個(gè)也就是保證了 insert 語(yǔ)句在復(fù)制到 slave 的時(shí)候還能生成和 master 那邊一樣的值(它保證了基于語(yǔ)句復(fù)制的安全);
  • 由于在這種模式下 auto_inc 鎖一直要保持到語(yǔ)句的結(jié)束,所以這個(gè)就影響了并發(fā)的插入。
consecutive

innodb_autoinc_lock_mode 為 1 時(shí),也就是 consecutive 級(jí)別。這是如果是單一的 insert SQL,可以立即獲得該鎖,并立即釋放,而不必等待當(dāng)前SQL執(zhí)行完成(除非在其它事務(wù)中已經(jīng)有 session 獲取了自增鎖)。另外當(dāng)SQL是一些批量 insert SQL 時(shí),比如 insert into ... select ...load data , replace ... select ... 時(shí),這時(shí)還是表級(jí)鎖,可以理解為退化為必須等待當(dāng)前 SQL 執(zhí)行完才釋放。可以認(rèn)為,該值為 1 時(shí)相對(duì)比較輕量級(jí)的鎖,也不會(huì)對(duì)復(fù)制產(chǎn)生影響,唯一的缺陷是產(chǎn)生自增值不一定是完全連續(xù)的

  • 這一模式下對(duì) simple insert 做了優(yōu)化,由于 simple insert 一次性插入的值的個(gè)數(shù)可以立馬得到確定,所以 MyQL 可以一次生成幾個(gè)連續(xù)的值,用于這個(gè) insert 語(yǔ)句。總得來(lái)說(shuō)這個(gè)對(duì)復(fù)制也是安全的(它保證了基于語(yǔ)句復(fù)制的安全);
  • 這一模式也是MySQL的默認(rèn)模式,這個(gè)模式的好處是 auto_inc 鎖不要一直保持到語(yǔ)句的結(jié)束,只要語(yǔ)句得到了相應(yīng)的值就可以提前釋放鎖。
interleaved

innodb_autoinc_lock_mode 為 2 時(shí),也就是 interleaved 級(jí)別。所有 insert 種類(lèi)的 SQL 都可以立馬獲得鎖并釋放,這時(shí)的效率最高。但是會(huì)引入一個(gè)新的問(wèn)題:當(dāng) binlog_format 為 statement 時(shí),這是復(fù)制沒(méi)法保證安全,因?yàn)榕康?insert,比如 insert ... select ... 語(yǔ)句在這個(gè)情況下,也可以立馬獲取到一大批的自增 id 值,不必鎖整個(gè)表, slave 在回放這個(gè) SQL 時(shí)必然會(huì)產(chǎn)生錯(cuò)亂。

  • 由于這個(gè)模式下已經(jīng)沒(méi)有了 auto_inc 鎖,所以這個(gè)模式下的性能是最好的,但是也有一個(gè)問(wèn)題,就是對(duì)于同一個(gè)語(yǔ)句來(lái)說(shuō)它所得到的 auto_incremant 值可能不是連續(xù)的。

如果你的二進(jìn)制文件格式是mixed | row 那么這三個(gè)值中的任何一個(gè)對(duì)于你來(lái)說(shuō)都是復(fù)制安全的。

由于現(xiàn)在mysql已經(jīng)推薦把二進(jìn)制的格式設(shè)置成row,所以在binlog_format不是statement的情況下最好是innodb_autoinc_lock_mode=2 這樣可能知道更好的性能。

總結(jié)

InnoDB鎖的特性

  1. 在不通過(guò)索引條件查詢(xún)的時(shí)候,InnoDB使用的確實(shí)是表鎖!
  2. 由于 MySQL 的行鎖是針對(duì)索引加的鎖,不是針對(duì)記錄加的鎖,所以雖然是訪問(wèn)不同行 的記錄,但是如果是使用相同的索引鍵,是會(huì)出現(xiàn)鎖沖突的。
  3. 當(dāng)表有多個(gè)索引的時(shí)候,不同的事務(wù)可以使用不同的索引鎖定不同的行,另外,不論 是使用主鍵索引、唯一索引或普通索引,InnoDB 都會(huì)使用行鎖來(lái)對(duì)數(shù)據(jù)加鎖。
  4. 即便在條件中使用了索引字段,但是否使用索引來(lái)檢索數(shù)據(jù)是由 MySQL 通過(guò)判斷不同 執(zhí)行計(jì)劃的代價(jià)來(lái)決定的,如果 MySQL 認(rèn)為全表掃 效率更高,比如對(duì)一些很小的表,它 就不會(huì)使用索引,這種情況下 InnoDB 將使用表鎖,而不是行鎖。因此,在分析鎖沖突時(shí), 別忘了檢查 SQL 的執(zhí)行計(jì)劃(explain查看),以確認(rèn)是否真正使用了索引。

鎖模式

鎖的模式有:讀意向鎖,寫(xiě)意向鎖,讀鎖,寫(xiě)鎖和自增鎖(auto_inc)。

不同模式鎖的兼容矩陣

ISIXSXAI
IS兼容兼容兼容
兼容
IX兼容兼容

兼容
S兼容
兼容

X




AI兼容兼容


總結(jié)起來(lái)有下面幾點(diǎn):

  • 意向鎖之間互不沖突;
  • S 鎖只和 S/IS 鎖兼容,和其他鎖都沖突;
  • X 鎖和其他所有鎖都沖突;
  • AI 鎖只和意向鎖兼容;

鎖的類(lèi)型

根據(jù)鎖的粒度可以把鎖細(xì)分為表鎖行鎖,行鎖根據(jù)場(chǎng)景的不同又可以進(jìn)一步細(xì)分,依次為 Next-Key LockGap Lock 間隙鎖Record Lock 記錄鎖插入意向 GAP 鎖

不同的鎖鎖定的位置是不同的,比如說(shuō)記錄鎖只鎖住對(duì)應(yīng)的記錄,而間隙鎖鎖住記錄和記錄之間的間隔,Next-Key Lock 則所屬記錄和記錄之前的間隙。不同類(lèi)型鎖的鎖定范圍大致如下圖所示。

不同類(lèi)型鎖的兼容矩陣

RECORDGAPNEXT-KEYII GAP
RECORD
兼容
兼容
GAP兼容兼容兼容兼容
NEXT-KEY
兼容
兼容
II GAP兼容

兼容

其中,第一行表示已有的鎖,第一列表示要加的鎖。插入意向鎖較為特殊,所以我們先對(duì)插入意向鎖做個(gè)總結(jié),如下:

  • 插入意向鎖不影響其他事務(wù)加其他任何鎖。也就是說(shuō),一個(gè)事務(wù)已經(jīng)獲取了插入意向鎖,對(duì)其他事務(wù)是沒(méi)有任何影響的;
  • 插入意向鎖與間隙鎖和 Next-key 鎖沖突。也就是說(shuō),一個(gè)事務(wù)想要獲取插入意向鎖,如果有其他事務(wù)已經(jīng)加了間隙鎖或 Next-key 鎖,則會(huì)阻塞。

其他類(lèi)型的鎖的規(guī)則較為簡(jiǎn)單:

  • 間隙鎖不和其他鎖(不包括插入意向鎖)沖突;
  • 記錄鎖和記錄鎖沖突,Next-key 鎖和 Next-key 鎖沖突,記錄鎖和 Next-key 鎖沖突;

感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享MySQL鎖類(lèi)型和加鎖原理是什么內(nèi)容對(duì)大家有幫助,同時(shí)也希望大家多多支持創(chuàng)新互聯(lián),關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,遇到問(wèn)題就找創(chuàng)新互聯(lián),詳細(xì)的解決方法等著你來(lái)學(xué)習(xí)!

文章標(biāo)題:MySQL鎖類(lèi)型和加鎖原理是什么
網(wǎng)頁(yè)網(wǎng)址:http://chinadenli.net/article36/goipsg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供品牌網(wǎng)站設(shè)計(jì)域名注冊(cè)用戶(hù)體驗(yàn)網(wǎng)站內(nèi)鏈自適應(yīng)網(wǎng)站移動(dòng)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話(huà):028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)