首頁 > 資料庫 > mysql教程 > 一起聊聊MYSQL中鎖的各種模式與類型

一起聊聊MYSQL中鎖的各種模式與類型

WBOY
發布: 2022-02-11 18:59:00
轉載
3126 人瀏覽過

這篇文章為大家帶來了關於mysql中鎖的各種類型與模式的相關知識,希望對大家有幫助。

一起聊聊MYSQL中鎖的各種模式與類型

在日常開發工作中,我們幾乎需要天天與資料庫打交道,作為一個只會CRUD的SQL BOY,除了每天用mybatis-generator自動產生DAO層程式碼之外,我們幾乎不用去care資料庫中如何處理並發請求,但是突然某一天MYSQL資料庫告警了,出現了死鎖,我們的內心慌的一匹,不禁想問:這不就是個普通查詢嗎,咋還鎖起來了?

為了避免慌亂的表情被主管捕捉到,我們需要事先了解資料庫中到底有哪些鎖定。

在MySQL中,其實將鎖定分成了兩類:鎖定類型(lock_type)和鎖定模式(lock_mode)。

鎖類型所描述的鎖的粒度,也就是把鎖具體加在什麼地方;而鎖模式描述的是到底加的是什麼鎖,是讀鎖還是寫鎖。鎖模式通常和鎖類型結合使用。

按鎖定的模式分

讀取鎖定

#讀取鎖定,又叫共用鎖定/S鎖定/share locks 。

讀鎖是某個事務(例如事務A)在進行讀取操作(例如讀取一張表或讀取某一行)時創建出來的鎖,其他的事務可以並發地讀取這些數據(被加了鎖的),但是不能修改這些資料(除非持有鎖的用戶已經釋放鎖)。

事務A對資料加上讀鎖之後,其他事務依然可以對其添加讀鎖(共享),但是不能添加寫鎖。

在記錄上加讀鎖定

InnoDB支援表鎖和行鎖,在行(也就是記錄)上加鎖,並不是鎖住該筆記錄,而是在記錄對應的索引上加鎖。如果where條件中不走索引,則會對所有的記錄加鎖。

明確加鎖語句為:

一起聊聊MYSQL中鎖的各種模式與類型

注意:這裡所說的讀,是指當前讀,快照讀是無需加鎖的。普通select讀一般都是快照讀,除了select...lock in share mode這樣的明確加鎖語句下會變成當前讀,在InnoDB引擎的serializable級別下,普通select讀也會變成快照讀。

另外要注意,對於行鎖的加鎖過程分析,要根據事務隔離等級、是否使用索引(哪種類型的索引)、記錄是否存在等因素結合分析,才能判斷在哪裡加上了鎖。

innodb引擎中的加讀鎖定的幾種情況

普通查詢在隔離層級為 serializable 會為記錄加上S鎖定。但這也取決於場景:非事務讀取(auto-commit)在Serializable 隔離等級下,無需加鎖;

Serializable隔離等級時:如果查詢條件為唯一索引且是唯一等值查詢時:是在該筆記錄上加S鎖;非唯一條件查詢(查詢會掃描到多筆記錄時):記錄本身記錄的間隙(需要具體分析間隙的範圍),加S鎖;

select … in share mode,會為記錄加S鎖,但是根據隔離等級的不同,加鎖的行為有所不同:

RC隔離等級:是在記錄上加S鎖。 RR/Serializable隔離等級:如果查詢條件為唯一索引且是唯一等值查詢時:是在該筆記錄上加S鎖;非唯一條件查詢(查詢會掃描到多筆記錄時):記錄本身記錄的間隙(需要具體分析間隙的範圍),加上S鎖;

通常insert操作是不加鎖的,但如果在插入或更新記錄時,檢查到duplicate key(或者有一個被標記刪除的duplicate key),對於普通的insert/update,會加S鎖,而對於類似replace into或insert … on duplicate 這樣的SQL語句加的是X鎖。

insert … select 插入資料時,會對select 的表上掃描到的資料加上S鎖;

外鍵檢查:當我們刪除一條父表上的記錄時,需要去檢查是否有引用約束,這時候會掃描子表上對應的記錄,並加上S鎖定。

在表上加讀鎖定

表鎖定由 MySQL伺服器實現,無論儲存引擎是什麼,都可以使用表鎖定。一般在執行 DDL 語句時,譬如 ALTER TABLE 時就會對整個表格加鎖。執行 SQL 語句時,也可以明確地對某個表格加鎖。

給表明確加鎖語句為:

一起聊聊MYSQL中鎖的各種模式與類型

在使用MYISAM引擎時,通常我們不需要手動加鎖,因為MYISAM引擎會針對我們的sql語句會自動進行加鎖,整個過程不需要使用者乾預:

  • 查詢語句(select):會自動為涉及的表加讀鎖定;

  • 更新語句(update、delete、insert):會自動為涉及的表加上寫鎖定。

寫鎖定

寫鎖,排他鎖/X鎖/exclusive locks。寫鎖的阻塞性比讀鎖要嚴格的多,一個事務對資料添加寫鎖之後,其他的事務對該數據,既不能讀取也不能更改。

與讀取鎖定加鎖的範圍相同,寫入鎖定既可以加在記錄上,也可以加在表上。

在記錄上加上寫鎖定

在記錄上加寫鎖定,引擎需要使用InnoDB。

通常普通的select語句是不會加鎖的(隔離等級為Serializable除外),想要在查詢時加入排他鎖需要使用以下語句:

查詢時加寫鎖定:

一起聊聊MYSQL中鎖的各種模式與類型

與加讀鎖定相同,寫鎖定也是加在索引上的。

更新時加上寫入鎖定:

一起聊聊MYSQL中鎖的各種模式與類型

#在表格上加寫鎖定

明確給表加上寫鎖定的語句為:

一起聊聊MYSQL中鎖的各種模式與類型

當引擎選擇myisam時,insert/update/delete語句,會自動給該表加上排他鎖定。

讀寫鎖定相容性:

  • 讀取鎖定是共用的,它不會阻塞其他讀鎖定,但會阻塞其他的寫入鎖定;

  • 寫鎖是排他的,它會阻塞其他讀鎖和寫鎖;

  • #總結:讀讀不互斥,讀寫互斥,寫寫互斥

意向鎖定

#意向鎖定是一種不與行級鎖定衝突的表格層級鎖定,表示表中的記錄所需要的鎖(S鎖或X鎖)的類型(其實就是告訴你,這張表中已經存在了行鎖(行鎖的類型),所以叫意向鎖)。 InnoDB支援多種粒度的鎖,允許行級鎖和表級鎖的共存。

意向鎖定分為:

意向共享鎖定(IS鎖定):IS鎖定表示當前交易意圖在表中的行上設定共享鎖定

下面語句執行時會先取得IS鎖,因為這個操作在取得S鎖:取得S鎖:select ... lock in share mode

意向排它鎖(IX鎖):IX鎖表示目前事務意圖在表中的行上設定排它鎖

下面語句執行時會先取得IX鎖,因為這個動作在取得X鎖:取得X鎖:select ... for update

交易要取得在某表上的S鎖和X鎖之前,必須先分別取得對應的IS鎖和IX鎖。

意向鎖有什麼作用呢:

如果另一個事務試圖在該表層級的共享鎖或排它鎖,則受到由第一個事務控制的表級意向鎖的阻塞。第二個交易在鎖定該表前不必檢查各個頁或行鎖​​,而只需檢查表上的意向鎖。

範例:表格test_user:

一起聊聊MYSQL中鎖的各種模式與類型

一起聊聊MYSQL中鎖的各種模式與類型

#交易A 取得了某一行的排他鎖,並未提交;

交易B 想要取得test_user 表的資料表共用鎖定;

因為共用鎖定與排他鎖定互斥,所以交易B 在試圖對test_user 表加上共用鎖定的時候,必須保證:

  • 目前沒有其他交易持有users 資料表的排他鎖定(表排他鎖)。

  • 目前沒有其他交易持有 users 表中任何一行的排他鎖定(行排他鎖)。

為了偵測是否符合第二個條件,交易 B 必須在確保 test_user表不存在任何排他鎖的前提下,去偵測表中的每一行是否存在排他鎖。很明顯這是一個效率很差的做法,但是有了意向鎖之後,情況就不一樣了:

因為此時事務A獲取了兩把鎖:users 表上的意向排他鎖與id為28 的資料行上的排他鎖。

交易B 想要取得test_user 表的共享鎖定:

交易B 只需要偵測交易A 是否持有test_user 表的意向排他鎖,就可以得知交易A 必然持有該表中某些資料行的排他鎖,那麼事務B 對test_users 表的加鎖請求就會被排斥(阻塞),從而無需去檢測表中的每一行資料是否存在排他鎖。

交易C 也想取得users 表中某一行的排他鎖:

  • #交易C 偵測到交易A 持有test_user 表的意向排他鎖定;

  • 意向鎖定之間並不互斥,所以交易C 取得到了test_user 表的意向排他鎖;

  • 因為id 為31 的資料行上不存在任何排他鎖,最終事務C 成功取得到了該資料行上的排他鎖。

意向鎖與意向鎖之間是不互斥的,但是意向鎖與其他表鎖之間存在一定的相容互斥,具體如下:

意向鎖定之間的相容互斥性:

一起聊聊MYSQL中鎖的各種模式與類型

意向鎖定與普通的排他/ 共享鎖定互斥:

一起聊聊MYSQL中鎖的各種模式與類型

#自增鎖

我們在設計表結構的時候,通常會把主鍵設定成自增長(思考為什麼?)。

在InnoDB儲存引擎中,針對每個自增長的欄位都設定了一個自增長的計數器。我們可以執行下面的語句來得到這個計數器的當前值:

一起聊聊MYSQL中鎖的各種模式與類型

當我們進行插入操作的時候,該操作會根據這個自增長的計數器的當前值進行1操作,並賦予自增長的列,這個操作我們稱之為auto-inc Locking,也就是自增長鎖,這種鎖其實採用的是特殊的表鎖機制,如果insert操作出現在一個事務中,這個鎖是在insert操作完成之後立即釋放,而不是等待交易提交。

按鎖的型別分

全域鎖定

#所謂全域鎖,其實就是要為整個資料庫實例加鎖。

資料庫實例與資料庫是有所區別的:

資料庫,就是保存資料的倉庫,具體到mysql中,資料庫其實是一系列資料檔案集合(也就是我們通常所說的database,例如建立資料庫語句就是create database...)。

資料庫實例,是指存取資料庫的應用程序,在Mysql中,就是mysqld進程了。

簡單來理解,資料庫實例中包含了你所建立的各種資料庫。

如果為資料庫實例加上全域鎖定會導致整個庫處於唯讀狀態(這是非常危險的)。

一般來說,全域鎖定的典型使用場景是用於全庫備份,也就是把資料庫中所有的表都select出來。但要注意,讓整個庫都處於唯讀狀態,會導致一些嚴重的問題:

  • #在主庫上加全域鎖,在加鎖期間,不能執行任何更新操作,業務基本上很多功能都不可用了;

  • 在從庫上加全域鎖,在加鎖期間,不能執行主從同步,會導致主從同步延遲。

全域鎖定的加鎖語句是:

一起聊聊MYSQL中鎖的各種模式與類型

#解除全域鎖定的方法是:

  • #斷開執行全域鎖定的session即可;

  • ##執行解鎖sql語句:unlock tables;

如果需要個資料庫備份的話,可以使用官方自備的邏輯備份工具mysqldump。

既然已經有了dump工具,為什麼還需要 FTWRL 呢?一致性讀是好,但前提是引擎要支援這個隔離等級。比如,MyISAM 這種不支援事務的引擎。這時,我們就需要使用 FTWRL 指令了。

FTWRL 前有讀寫的話,FTWRL 都會等待讀寫執行完畢後才執行。

FTWRL 執行的時候要刷髒頁的資料到磁碟,因為要保持資料的一致性 ,所以執行FTWRL時候是所有交易都提交完畢的時候。

全域鎖的實作還是依賴元資料鎖的。

元資料鎖

元資料鎖(MetaData Lock),也叫MDL鎖,是用來保護元資料訊息,系統級的鎖無法主動控制。在MySQL5.5版本,開始引入MDL鎖定,主要是為了在並發環境下對DDL、DML同時操作下保持元資料的一致性。例如下面這種情況:

隔離等級:RR

一起聊聊MYSQL中鎖的各種模式與類型

如果沒有元資料鎖的保護,那麼交易2可以直接執行DDL操作,導致事務1出錯。 MYSQL5.5版本的時候加入 MDL 鎖,是為了保護這種情況的發生。由於事務1開啟了查詢,那麼獲得了元資料鎖,鎖的模式為MDL讀鎖,事務2要執行DDL,則需獲得MDL 寫鎖,由於讀寫鎖互斥,所以事務2需要等待事務1釋放掉讀鎖才能執行。

  • 對錶中的記錄進行增刪改查(DML操作)的時候,自動加上MDL讀鎖定;

  • 對錶的結構(DDL操作)進行修改的時候,自動加MDL寫鎖。

MDL鎖定的粒度

#MDL鎖定是Mysql伺服器層面中實現的,而不是在儲存引擎插件中實現。依照鎖定的範圍,MDL鎖定可以分為以下幾類:

一起聊聊MYSQL中鎖的各種模式與類型

MDL鎖定的模式

一起聊聊MYSQL中鎖的各種模式與類型

#頁級鎖定

#MySQL中鎖定粒度介於行級鎖定和表級鎖定中間的一種鎖定。表級鎖定速度快,但衝突多,行級衝突少,但速度慢。所以取了折衷的頁級,一次鎖定鄰近的一組記錄。不同的儲存引擎支援不同的鎖定機制。根據不同的儲存引擎,MySQL中鎖定的特性可以大致歸納如下:

一起聊聊MYSQL中鎖的各種模式與類型

#頁級鎖定是MySQL中比較獨特的一種鎖定級別,套用到BDB引擎,並發度一般,頁級鎖定的特點是鎖定顆粒度介於行級鎖定與表級鎖之間,所以獲取鎖定所需的資源開銷,以及所能提供的並發處理能力也同樣是介於上面二者之間。另外,頁級鎖定和行級鎖定一樣,會發生死鎖。

鎖定粒度大小比較:表級鎖定> 頁級鎖定>行級鎖定

表級鎖定

表鎖在上文我們已經介紹過,相較於行鎖的細粒度加鎖,表鎖是對整張表加鎖。由於是對整張表加鎖,就沒有行鎖的加鎖方式那麼複雜,所以加鎖比行鎖快,而且不會出現死鎖的情況(因為事務是一次性獲取想要加的表表鎖),但是表鎖也存在一些問題:鎖的範圍太大,在並發比較高的情況下,會導致搶鎖的衝突機率變高,這樣並發性能就大打折扣了。

表鎖的加鎖方式

一起聊聊MYSQL中鎖的各種模式與類型

#引擎選擇MYISAM時

MYISAM引擎只支援表鎖,不支援行鎖。
  • 手動新增表格級鎖定的語句如下:

  • 在使用MYISAM引擎時,通常我們不需要手動加鎖,因為MYISAM引擎會針對我們的sql語句會自動進行加鎖,整個過程不需要使用者乾預:

查詢語句(select):會自動為涉及的表加讀鎖定;更新語句(update、delete、insert):會自動為涉及的表加上寫入鎖定

引擎選擇InnoDB時

    InnoDB引擎同時支援行級鎖定和表格級鎖定,預設為行級鎖定。
  • 為InnoDB引擎的資料表手動加鎖,也同樣使用 lock table {tableName} read/write 語句進行讀取/寫入鎖定的新增。

  • 除此之外,innodb也支援一種表級鎖定:意向鎖(上文已經介紹過)。
  • 總的來說,InnoDB引擎的表格層級鎖定包含五種鎖定模式:

  • #LOCK_IS:表格意圖讀取鎖定

  • LOCK_IX:表格意圖寫入鎖定

  • LOCK_S:表格讀取鎖定

LOCK_X:表格寫鎖定

LOCK_AUTO_INC:自增鎖

  • #行級鎖定
  • 在撰寫業務程式碼的過程中,我們接觸最多的就是行級鎖了(表級鎖由於效能問題,一般不建議使用)。相較於表級鎖,行級鎖具有明顯的效能優勢:
  • 衝突少:多執行緒中存取不同的記錄時只存在少量鎖定衝突;

#鎖定的粒度小:可以長時間鎖定單一的行,對其他的行沒有影響,所以並發度是最高的;

但是使用行鎖時,一旦稍不注意,是非常容易出現死鎖的(表鎖就不存在死鎖現象),所以使用行鎖需要注意加鎖的順序和鎖定的範圍。

###InnoDB的行鎖是透過對索引項目加鎖實現的,這表示只有透過索引查詢記錄時才會使用行鎖,如果不走索引查詢資料將使用表鎖,則效能會大打折扣。 ######要記住:行鎖也叫記錄鎖,記錄鎖都是加在索引上的。 ############where條件指定的是主鍵索引:則在主鍵索引上加鎖;############wehre條件指定的是二級索引:記錄鎖定不僅會加在這個二級索引上,還會加在這個二級索引所對應的叢集索引上;############where條件如果無法走索引:MySQL會給整張表所有資料行加記錄鎖,儲存引擎層將所有記錄傳回由MySQL服務端進行過濾。 ##################記錄鎖定:LOCK_REC_NOT_GAP(只鎖定記錄)############記錄鎖定是最簡單的行鎖定。例如在RR隔離等級時,執行 select * from t_user where id = 1 for update 語句時,實際上是對 id = 1 (這裡id為主鍵)這條記錄上鎖(鎖加在聚簇索引上)。 ###

記錄鎖永遠都是加在索引上的,就算一個表沒有建立索引,資料庫也會隱含的建立一個索引。如果 WHERE 條件中指定的欄位是個二級索引,那麼記錄鎖定不僅會加在這個二級索引上,還會加在這個二級索引所對應的叢集索引上。

注意,如果 SQL 語句無法使用​​索引時會走主索引實作全表掃描,這個時候 MySQL 會為整個表的所有資料行加上記錄鎖定。

如果一個 WHERE 條件無法透過索引快速過濾,儲存引擎層面就會將所有記錄加鎖後傳回,再由 MySQL Server 層進行過濾。在沒有索引時,不僅會消耗大量的鎖定資源,增加資料庫的開銷,而且極大的降低了資料庫的並發效能,所以說,更新作業一定要記得走索引(因為更新作業會加X鎖定)。

行級鎖的幾種類型:

間隙鎖:LOCK_GAP(只鎖間隙)

間隙鎖是一種區間鎖。鎖加在不存在的空閒空間上,或者兩個索引記錄之間,或者第一個索引記錄,或者最後一個索引之後的空間,用來表示只鎖住一段範圍(一般在進行範圍查詢時且隔離級別在RR或Serializable隔時)。

一般在RR隔離等級下會使用到GAP鎖定。使用GAP鎖,主要是為了防止幻讀產生,在被GAP鎖鎖住的區間,不允許插入資料或更新資料。

間隙鎖的產生條件:innodb的隔離等級為 Repeatable Read 或 Serializable。

間隙鎖定的作用範圍說明:

隔離等級:RR

一起聊聊MYSQL中鎖的各種模式與類型

#以Student表作為範例數據,id為主鍵, stu_code為學生編號,新增普通索引。

間隙鎖定區域定義:

根據檢索條件向左尋找最靠近的值A,作為左區間,向右尋找最靠近的值B,作為右區間,間隙鎖定為( A,B)

向左找不到最近的值A,也是就無窮小,作為左區間,向右尋找最靠近的值B,作為右區間,間隙鎖為(無窮小,B)

向左找到最近的值A,作為左區間,向右尋找不到最近的值B,也就是無窮大,作為右區間,間隙鎖為(A,無窮大)

區間(A,B)範例:

事務1:

select * from student where stu_code = 4 for update
登入後複製

事務2:

insert into student vaues(2, 2, 'A');
insert into student values(4, 5, 'B');
登入後複製

根據事務1的sql語句分析,間隙鎖的範圍是:stu_code = 4記錄是存在的,所以左區間為最近的索引值為stu_code = 3,右區間為最近的索引值為stu_code =7,所以間隙範圍為:(3,7),因此事務2的兩個insert 語句,一個在範圍外,一個在範圍內,在範圍外的能插入,而範圍內的則阻塞,所以(2,2, 'A')能插入成功;(4,5, 'B')插入阻塞。

區間(無窮小,B)範例:

交易1:

select * from student where stu_code = 1 for update
登入後複製

交易2:

insert into student vaues(2, 0, 'c');
insert into student vaues(2, 2, 'r');
insert into student vaues(5, 2, 'o');
登入後複製

根據交易1的sql語句分析,間隙鎖的範圍是:stu_code = 1 是存在的,左邊最近沒有記錄,所以是左邊的無窮小,右邊最近的索引值為stu_code = 3,所以間隙鎖範圍為:(無窮小,3)。所以事務2的第一個和第二個insert sql語句執行被阻塞,是在間隙鎖範圍內的。第三個insert sql語句能執行成功,不在間隙鎖定範圍內。

區間(A,無窮大)範例:

交易1:

select * from student where stu_code = 7 for update
登入後複製

交易2:

insert into student vaues(2, 2, 'm');
insert into student vaues(20, 22, 'j');
登入後複製
登入後複製

根據交易1的sql語句分析,間隙鎖的範圍是:stu_code = 7 是存在的,左邊最近的索引值為stu_code = 4,而右邊是沒有索引值的,所以間隙鎖的範圍為:(4,無限大),第一個inset語句能執行成功,不在間隙範圍內;第二個insert語句執行被阻塞,是在間隙鎖範圍內的。

如果查詢語句在資料庫中沒有記錄,那該怎麼鎖呢?

以上是查詢是有記錄的,如果查詢語句在資料庫中沒有記錄,那該怎麼鎖呢?咱們繼續往下:

事務1:

update student set stu_name = '000' where stu_code = 10
登入後複製

交易2:

insert into student vaues(2, 2, 'm');
insert into student vaues(20, 22, 'j');
登入後複製
登入後複製

根據上面的執行語句是找不到記錄的,向左取最近的記錄( 10,7,'小明')作為左區間,即間隙鎖的範圍是:(7, 無窮大),第一個insert語句不在區間範圍內,能執行成功;第二個insert執行語句在區間內被阻塞,執行失敗。如果事務1的where 條件是大於10,也是向左找最近的記錄值作為左區間,所以間隙鎖的範圍也是:(7, 無窮大)

總結:間隙鎖產生的條件

RR/Serializable隔離等級下:Select ... Where...For Update 時:

#只使用唯一索引查詢,且只鎖定一筆記錄時,InnoDB會使用行鎖定。

只使用唯一索引查詢,但是檢索條件是範圍檢索,或是唯一檢索然而檢索結果不存在(試圖鎖住不存在的資料)時,會產生 Next-Key Lock。

使用普通索引檢索時,不管是何種查詢,只要加鎖,都會產生間隙鎖定。

同時使用唯一索引和普通索引時,由於資料行是優先根據普通索引排序,再根據唯一索引排序,所以也會產生間隙鎖定。

下一鍵鎖:LOCK_ORDINARY,也稱為Next-Key Lock

Next-Key鎖定是 record lock gap lock 的組合。和間隙鎖一樣,在 RC 隔離等級下沒有 Next-key 鎖(除非透過修改配置強制開啟),只有 RR/Serializable隔離等級才有。

MySQL InnoDB工作在可重複讀取隔離等級(RR)下,並且會以Next-Key Lock的方式對資料行進行加鎖,這樣可以有效防止幻讀的發生。 Next-Key Lock是行鎖定和間隙鎖定的組合,當InnoDB掃描索引記錄的時候,會先對索引記錄加上行鎖定(Record Lock),再對索引記錄兩邊的間隙加上間隙鎖定(Gap Lock)。加上間隙鎖之後,其他事務就不能在這個間隙修改或插入記錄。

當查詢的索引含有唯一屬性(唯一索引,主鍵索引)時,Innodb儲存引擎會對next-key lock進行最佳化,將其降為record lock,即僅鎖定索引本身,而不是範圍。

插入意圖鎖:LOCK_INSERT_INTENSION

#插入意圖鎖,插入記錄時使用,是一種特殊的間隙鎖。這個鎖表示插入的意向,只有在執行insert語句的時候才會有這個鎖。

假設有索引記錄的值分別是id = 1和id = 5(1到5之間沒有記錄),單獨的事務分別嘗試插入id = 2和id = 3,在獲得插入行的在排它鎖之前,每個事務都是用插入意圖鎖來鎖定1和5之間的空間,但不會互相阻塞。因為插入意向鎖之間是不會衝突的。

插入意向鎖定會跟間隙鎖定或Next-Key鎖定衝突:間隙鎖的作用是鎖住區間防止其他交易插入資料導致幻讀。

在上面的場景中,假設提前有事務A獲取了id 在(1,5)區間的間隙鎖,那麼事務B嘗試插入id = 2時,會先嘗試獲取插入意向鎖,但是由於插入意向鎖和間隙鎖衝突,導致插入失敗,也就避免了幻讀產生。

結語

MYSQL的鎖定機制非常複雜,在實際的開發工作中,對於隔離層級的設定都需要非常謹慎,例如RR等級會比RC等級多出一個間隙鎖,這可能會導致嚴重的效能問題。本文從鎖的模式和鎖的範圍對MYSQL鎖的分類進行了簡單介紹,希望我們在面向資料庫開發的過程中,能夠仔細分析研究我們的SQL語句是否合理(尤其需要注意是否會產生死鎖等問題)!

推薦學習:mysql影片教學

#

以上是一起聊聊MYSQL中鎖的各種模式與類型的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
來源:juejin.im
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板