自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

數(shù)據(jù)庫鎖的12連問,抗?。?/h1>

數(shù)據(jù)庫 其他數(shù)據(jù)庫
如果查詢條件的是唯一索引,或者主鍵時(shí),Next-Key Lock?會(huì)降為Record Lock?。如果是普通索引,將對(duì)下一個(gè)鍵值加上gap lock?,其實(shí)就是對(duì)下一個(gè)鍵值的范圍為加鎖。gap lock間隙鎖,就是為了解決幻讀問題而設(shè)計(jì)出來的。

?前言

大家好,我是田螺。

金三銀四很快就要來啦,準(zhǔn)備了數(shù)據(jù)庫鎖的12連問,相信大家看完肯定會(huì)有幫助的。

圖片

1. 為什么需要加鎖

在日常生活中,如果你心情不好想靜靜,不想被比別人打擾,你就可以把自己關(guān)進(jìn)房間里,并且反鎖。這就是生活中的加鎖。

同理,對(duì)于MySQL數(shù)據(jù)庫來說的話,一般的對(duì)象都是一個(gè)事務(wù)一個(gè)事務(wù)來說的。所以,如果一個(gè)事務(wù)內(nèi),一個(gè)SQL正在更新某條記錄,我們肯定不想它被別的事務(wù)影響到嘛?因此,數(shù)據(jù)庫設(shè)計(jì)大叔,給該行數(shù)據(jù)加上鎖(行鎖)。

專業(yè)一點(diǎn)的說法: 如果有多個(gè)并發(fā)請(qǐng)求存取數(shù)據(jù),在數(shù)據(jù)就可能會(huì)產(chǎn)生多個(gè)事務(wù)同時(shí)操作同一行數(shù)據(jù)。如果并發(fā)操作不加控制,不加鎖的話,就可能寫入了不正確的數(shù)據(jù),或者導(dǎo)致讀取了不正確的數(shù)據(jù),破壞了數(shù)據(jù)的一致性。因此需要考慮加鎖。

2. InnoDB有哪些鎖?

圖片

2.1 共享/排他鎖

InnoDB呢實(shí)現(xiàn)了兩種標(biāo)準(zhǔn)的行級(jí)鎖:共享鎖(簡稱S鎖)、排他鎖(簡稱X鎖)。

  • 共享鎖:簡稱為S鎖,在事務(wù)要讀取一條記錄時(shí),需要先獲取該記錄的S鎖。
  • 排他鎖:簡稱X鎖,在事務(wù)需要改動(dòng)一條記錄時(shí),需要先獲取該記錄的X鎖。

如果事務(wù)T1?持有行R的S?鎖,那么另一個(gè)事務(wù)T2請(qǐng)求訪問這條記錄時(shí),會(huì)做如下處理:

  • T2 請(qǐng)求S鎖立即被允許,結(jié)果T1和T2都持有R行的S鎖
  • T2 請(qǐng)求X鎖不能被立即允許,此操作會(huì)阻塞

如果T1?持有行R的X?鎖,那么T2?請(qǐng)求R的X、S?鎖都不能被立即允許,T2?必須等待T1?釋放X?鎖才可以,因?yàn)閄鎖與任何的鎖都不兼容。

S鎖和X鎖的兼容關(guān)系如下圖表格:

圖片

X?鎖和S?鎖是對(duì)于行記錄來說的話,因此可以稱它們?yōu)樾屑?jí)鎖或者行鎖。我們認(rèn)為行鎖的粒度就比較細(xì),其實(shí)一個(gè)事務(wù)也可以在表級(jí)別下加鎖,對(duì)應(yīng)的,我們稱之為表鎖。給表加的鎖,也是可以分為X?鎖和S鎖的哈。

如果一個(gè)事務(wù)給表已經(jīng)加了S鎖,則:

  • 別的事務(wù)可以繼續(xù)獲得該表的S鎖,也可以獲得該表中某些記錄的S鎖。
  • 別的事務(wù)不可以繼續(xù)獲得該表的X鎖,也不可以獲得該表中某些記錄的X鎖。

如果一個(gè)事務(wù)給表加了X鎖,那么

  • 別的事務(wù)不可以獲得該表的S鎖,也不可以獲得該表某些記錄的S鎖。
  • 別的事務(wù)不可以獲得該表的X鎖,也不可以繼續(xù)獲得該表某些記錄的X鎖。

2.2 意向鎖

什么是意向鎖呢?意向鎖是一種不與行級(jí)鎖沖突的表級(jí)鎖。未來的某個(gè)時(shí)刻,事務(wù)可能要加共享或者排它鎖時(shí),先提前聲明一個(gè)意向。注意一下,意向鎖,是一個(gè)表級(jí)別的鎖哈。

為什么需要意向鎖呢? 或者換個(gè)通俗的說法,為什么要加共享鎖或排他鎖時(shí)的時(shí)候,需要提前聲明個(gè)意向鎖呢呢?

因?yàn)镮nnoDB是支持表鎖和行鎖共存的,如果一個(gè)事務(wù)A獲取到某一行的排他鎖,并未提交,這時(shí)候事務(wù)B請(qǐng)求獲取同一個(gè)表的表共享鎖。因?yàn)楣蚕礞i和排他鎖是互斥的,因此事務(wù)B想對(duì)這個(gè)表加共享鎖時(shí),需要保證沒有其他事務(wù)持有這個(gè)表的表排他鎖,同時(shí)還要保證沒有其他事務(wù)持有表中任意一行的排他鎖。

然后問題來了,你要保證沒有其他事務(wù)持有表中任意一行的排他鎖的話,去遍歷每一行?這樣顯然是一個(gè)效率很差的做法。為了解決這個(gè)問題,InnoDb的設(shè)計(jì)大叔提出了意向鎖。

意向鎖是如何解決這個(gè)問題的呢? 

意向鎖分為兩類:

  • 意向共享鎖:簡稱IS鎖,當(dāng)事務(wù)準(zhǔn)備在某些記錄上加S鎖時(shí),需要現(xiàn)在表級(jí)別加一個(gè)IS鎖。
  • 意向排他鎖:簡稱IX鎖,當(dāng)事務(wù)準(zhǔn)備在某條記錄上加上X鎖時(shí),需要現(xiàn)在表級(jí)別加一個(gè)IX鎖。

比如:

  • select ... lock in share mode?,要給表設(shè)置IS鎖;
  • select ... for update?,要給表設(shè)置IX鎖;

意向鎖又是如何解決這個(gè)效率低的問題呢:

如果一個(gè)事務(wù)A獲取到某一行的排他鎖,并未提交,這時(shí)候表上就有意向排他鎖?和這一行的排他鎖?。這時(shí)候事務(wù)B想要獲取這個(gè)表的共享鎖,此時(shí)因?yàn)闄z測到事務(wù)A持有了表的意向排他鎖,因此事務(wù)A必然持有某些行的排他鎖,也就是說事務(wù)B對(duì)表的加鎖請(qǐng)求需要阻塞等待,不再需要去檢測表的每一行數(shù)據(jù)是否存在排他鎖啦。

意向鎖僅僅表明意向的鎖,意向鎖之間不會(huì)互斥,是可以并行的,整體兼容性如下:

圖片

2.3 記錄鎖(Record Lock)

記錄鎖是最簡單的行鎖,僅僅鎖住一行。如:SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE,如果C1字段是主鍵或者是唯一索引的話,這個(gè)SQL會(huì)加一個(gè)記錄鎖(Record Lock)

記錄鎖永遠(yuǎn)都是加在索引上的,即使一個(gè)表沒有索引,InnoDB也會(huì)隱式的創(chuàng)建一個(gè)索引,并使用這個(gè)索引實(shí)施記錄鎖。它會(huì)阻塞其他事務(wù)對(duì)這行記錄的插入、更新、刪除。

一般我們看死鎖日志時(shí),都是找關(guān)鍵詞,比如lock_mode X locks rec but not gap),就表示一個(gè)X型的記錄鎖。記錄鎖的關(guān)鍵詞就是rec but not gap。以下就是一個(gè)記錄鎖的日志:

RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t` 
trx id 10078 lock_mode X locks rec but not gap
Record lock, heap no 2 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 4; hex 8000000a; asc ;;
1: len 6; hex 00000000274f; asc 'O;;
2: len 7; hex b60000019d0110; asc ;;

2.4 間隙鎖(Gap Lock)

為了解決幻讀問題,InnoDB引入了間隙鎖(Gap Lock)。間隙鎖是一種加在兩個(gè)索引之間的鎖,或者加在第一個(gè)索引之前,或最后一個(gè)索引之后的間隙。它鎖住的是一個(gè)區(qū)間,而不僅僅是這個(gè)區(qū)間中的每一條數(shù)據(jù)。

比如lock_mode X locks gap before rec表示X型gap鎖。以下就是一個(gè)間隙鎖的日志:

RECORD LOCKS space id 177 page no 4 n bits 80 index idx_name of table `test2`.`account` 
trx id 38049 lock_mode X locks gap before rec
Record lock, heap no 6 PHYSICAL RECORD: n_fields 2; compact format; info bits 0
0: len 3; hex 576569; asc Wei;;
1: len 4; hex 80000002; asc ;;

2.5 臨鍵鎖(Next-Key Lock)

Next-key鎖是記錄鎖和間隙鎖的組合,它指的是加在某條記錄以及這條記錄前面間隙上的鎖。說得更具體一點(diǎn)就是:臨鍵鎖會(huì)封鎖索引記錄本身,以及索引記錄之前的區(qū)間,即它的鎖區(qū)間是前開后閉,比如(5,10]。

如果一個(gè)會(huì)話占有了索引記錄R的共享/排他鎖,其他會(huì)話不能立刻在R之前的區(qū)間插入新的索引記錄。

If one session has a shared or exclusive lock on record R in an index, another session cannot insert a new index record in the gap immediately before R in the index order.

2.6 插入意向鎖

插入意向鎖,是插入一行記錄操作之前設(shè)置的一種間隙鎖,這個(gè)鎖釋放了一種插入方式的信號(hào)。它解決的問題:多個(gè)事務(wù),在同一個(gè)索引,同一個(gè)范圍區(qū)間插入記錄時(shí),如果插入的位置不沖突,不會(huì)阻塞彼此。

假設(shè)有索引值4、7,幾個(gè)不同的事務(wù)準(zhǔn)備插入5、6,每個(gè)鎖都在獲得插入行的獨(dú)占鎖之前用插入意向鎖各自鎖住了4、7之間的間隙,但是不阻塞對(duì)方因?yàn)椴迦胄胁粵_突。以下就是一個(gè)插入意向鎖的日志:

RECORD LOCKS space id 31 page no 3 n bits 72 index `PRIMARY` of table `test`.`child`
trx id 8731 lock_mode X locks gap before rec insert intention waiting
Record lock, heap no 3 PHYSICAL RECORD: n_fields 3; compact format; info bits 0
0: len 4; hex 80000066; asc f;;
1: len 6; hex 000000002215; asc " ;;
2: len 7; hex 9000000172011c; asc r ;;...

鎖模式兼容矩陣(橫向是已持有鎖,縱向是正在請(qǐng)求的鎖):

圖片

2.7 自增鎖

自增鎖是一種特殊的表級(jí)別鎖。它是專門針對(duì)AUTO_INCREMENT類型的列,對(duì)于這種列,如果表中新增數(shù)據(jù)時(shí)就會(huì)去持有自增鎖。簡言之,如果一個(gè)事務(wù)正在往表中插入記錄,所有其他事務(wù)的插入必須等待,以便第一個(gè)事務(wù)插入的行,是連續(xù)的主鍵值。

官方文檔是這么描述的:

An AUTO-INC lock is a special table-level lock taken by transactions inserting into tables with AUTO_INCREMENT columns. In the simplest case, if one transaction is inserting values into the table, any other transactions must wait to do their own inserts into that table, so that rows inserted by the first transaction receive consecutive primary key values.

假設(shè)有表:

mysql> create table t0 (id int NOT NULL AUTO_INCREMENT,name varchar(16),primary key ( id));

mysql> show variables like '%innodb_autoinc_lock_mode%';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| innodb_autoinc_lock_mode | 1 |
+--------------------------+-------+
1 row in set, 1 warning (0.01 sec)

設(shè)置事務(wù)A和B交替執(zhí)行流程如下:

圖片

通過上圖我們可以看到,當(dāng)我們?cè)谑聞?wù)A中進(jìn)行自增列的插入操作時(shí),另外會(huì)話事務(wù)B也進(jìn)行插入操作,這種情況下會(huì)發(fā)生2個(gè)奇怪的現(xiàn)象:

  • 事務(wù)A會(huì)話中的自增列好像直接增加了2個(gè)值。(如上圖中步驟7、8)
  • 事務(wù)B會(huì)話中的自增列直接從2開始增加的。(如上圖步驟5、6)

自增鎖是一個(gè)表級(jí)別鎖,那為什么會(huì)話A事務(wù)還沒結(jié)束,事務(wù)B可以執(zhí)行插入成功呢?不是應(yīng)該鎖表嘛?這是因?yàn)樵趨?shù)innodb_autoinc_lock_mode?上,這個(gè)參數(shù)設(shè)置為1?的時(shí)候,相當(dāng)于將這種auto_inc lock?弱化為了一個(gè)更輕量級(jí)的互斥自增長機(jī)制去實(shí)現(xiàn),官方稱之為mutex。

innodb_autoinc_lock_mode還可以設(shè)置為0或者2,

  • 0:表示傳統(tǒng)鎖模式,使用表級(jí)AUTO_INC鎖。一個(gè)事務(wù)的INSERT-LIKE語句在語句執(zhí)行結(jié)束后釋放AUTO_INC表級(jí)鎖,而不是在事務(wù)結(jié)束后釋放。
  • 1: 連續(xù)鎖模式,連續(xù)鎖模式對(duì)于Simple inserts不會(huì)使用表級(jí)鎖,而是使用一個(gè)輕量級(jí)鎖來生成自增值,因?yàn)镮nnoDB可以提前直到插入多少行數(shù)據(jù)。自增值生成階段使用輕量級(jí)互斥鎖來生成所有的值,而不是一直加鎖直到插入完成。對(duì)于bulk inserts類語句使用AUTO_INC表級(jí)鎖直到語句完成。
  • 2:交錯(cuò)鎖模式,所有的INSERT-LIKE語句都不使用表級(jí)鎖,而是使用輕量級(jí)互斥鎖。
  • INSERT-LIKE:指所有的插入語句,包括:INSERT、REPLACE、INSERT…SELECT、REPLACE…SELECT,LOAD DATA等。
  • Simple inserts:指在插入前就能確定插入行數(shù)的語句,包括:INSERT、REPLACE,不包含INSERT…ON DUPLICATE KEY UPDATE這類語句。
  • Bulk inserts: 指在插入錢不能確定行數(shù)的語句,包括:INSERT … SELECT/REPLACE … SELECT/LOAD DATA。

3. 什么是死鎖?如何防止死鎖?

什么是死鎖?

死鎖是指兩個(gè)或多個(gè)事務(wù)在同一資源上相互占用,并請(qǐng)求鎖定對(duì)方的資源,從而導(dǎo)致惡性循環(huán)的現(xiàn)象。

圖片

如何防止死鎖?

  • 盡量約定固定的順序訪問表,因?yàn)榻徊嬖L問更容易造成事務(wù)等待回路。
  • 盡量避免大事務(wù),建議拆成多個(gè)小事務(wù)。因?yàn)榇笫聞?wù)占用的鎖資源越多,越容易出現(xiàn)死鎖。
  • 降低數(shù)據(jù)庫隔離級(jí)別,比如RR降低為RC,因?yàn)镽R隔離級(jí)別,存在GAP鎖,死鎖概率大很多。
  • 死鎖與索引是密不可分的,合理優(yōu)化你的索引,死鎖概率降低。
  • 如果業(yè)務(wù)處理不好可以用分布式事務(wù)鎖或者使用樂觀鎖

4.數(shù)據(jù)庫的樂觀鎖和悲觀鎖

悲觀鎖:

悲觀鎖她專一且缺乏安全感了,她的心只屬于當(dāng)前事務(wù),每時(shí)每刻都擔(dān)心著它 心愛的數(shù)據(jù)可能被別的事務(wù)修改,所以一個(gè)事務(wù)擁有(獲得)悲觀鎖后,其他任何事務(wù)都不能對(duì)數(shù)據(jù)進(jìn)行修改啦,只能等待鎖被釋放才可以執(zhí)行。select…for update就是MySQL悲觀鎖的應(yīng)用。

圖片

樂觀鎖:

樂觀鎖的“樂觀情緒”體現(xiàn)在,它認(rèn)為數(shù)據(jù)的變動(dòng)不會(huì)太頻繁。因此,它允許多個(gè)事務(wù)同時(shí)對(duì)數(shù)據(jù)進(jìn)行變動(dòng)。實(shí)現(xiàn)方式:樂觀鎖一般會(huì)通過version版本號(hào)/時(shí)間戳判斷記錄是否被更改過,一般配合CAS算法實(shí)現(xiàn)。

圖片

大家可以看下這篇文章哈:圖文并茂的帶你徹底理解悲觀鎖與樂觀鎖

5. select for update加的是表鎖還是行鎖

這道面試題,一般需要分兩種數(shù)據(jù)庫隔離級(jí)別(RR和RC),還需要分查詢條件是唯一索引、主鍵、一般索引、無索引等幾種情況分開討論

在RC隔離級(jí)別下

  • 如果查詢條件是唯一索引,會(huì)加IX意向排他鎖(表級(jí)別的鎖,不影響插入)、兩把X排他鎖(行鎖,分別對(duì)應(yīng)唯一索引,主鍵索引)
  • 如果查詢條件是主鍵,會(huì)加IX意向排他鎖(表級(jí)別的鎖,不影響插入)、一把對(duì)應(yīng)主鍵的X排他鎖(行鎖,會(huì)鎖住主鍵索引那一行)。
  • 如果查詢條件是普通索引,如果查詢命中記錄,會(huì)加IX意向排他鎖(表鎖)、兩把X排他鎖(行鎖,分別對(duì)應(yīng)普通索引的X鎖,對(duì)應(yīng)主鍵的X鎖);如果沒有命中數(shù)據(jù)庫表的記錄,只加了一把IX意向排他鎖(表鎖,不影響插入)
  • 如果查詢條件是無索引,會(huì)加兩把鎖,IX意向排他鎖(表鎖)、一把X排他鎖(行鎖,對(duì)應(yīng)主鍵的X鎖)。

查詢條件是無索引,為什么不鎖表呢?MySQL會(huì)走聚簇(主鍵)索引進(jìn)行全表掃描過濾。每條記錄都會(huì)加上X鎖。但是,為了效率考慮,MySQL在這方面進(jìn)行了改進(jìn),在掃描過程中,若記錄不滿足過濾條件,會(huì)進(jìn)行解鎖操作。同時(shí)優(yōu)化違背了2PL原則。

在RR隔離級(jí)別

  • 如果查詢條件是唯一索引,命中數(shù)據(jù)庫表記錄時(shí),一共會(huì)加三把鎖:一把IX意向排他鎖 (表鎖,不影響插入),一把對(duì)應(yīng)主鍵的X排他鎖(行鎖),一把對(duì)應(yīng)唯一索引的X排他鎖 (行鎖)。
  • 如果查詢條件是主鍵,會(huì)加IX意向排他鎖(表級(jí)別的鎖,不影響插入)、一把對(duì)應(yīng)主鍵的X排他鎖(行鎖,會(huì)鎖住主鍵索引那一行)。
  • 如果查詢條件是普通索引,命中查詢記錄的話,除了會(huì)加X鎖(行鎖),IX鎖(表鎖,不影響插入),還會(huì)加Gap 鎖(間隙鎖,會(huì)影響插入)。
  • 如果查詢條件是無索引,會(huì)加一個(gè)IX鎖(表鎖,不影響插入),每一行實(shí)際記錄行的X鎖,還有對(duì)應(yīng)于supremum pseudo-record的虛擬全表行鎖。這種場景,通俗點(diǎn)講,其實(shí)就是鎖表了。

大家可以看下我之前寫的這篇文章哈:聊聊select for update到底加了什么鎖

6.如何使用數(shù)據(jù)庫分布式鎖

一般可以使用select ... for update來實(shí)現(xiàn)數(shù)據(jù)庫的分布式鎖。它的優(yōu)點(diǎn)是:簡單,使用方便,不需要引入Redis、zookeeper等中間件。缺點(diǎn)是:不適合高并發(fā)的場景,db操作性能較差。

我之前這篇文章,有詳細(xì)介紹數(shù)據(jù)庫分布式鎖的實(shí)現(xiàn),大家可以看看哈:面試必備:聊聊分布式鎖的多種實(shí)現(xiàn)!

7.表級(jí)鎖和行級(jí)鎖,頁面鎖有什么區(qū)別

不同的存儲(chǔ)引擎:

  • MyISAM存儲(chǔ)引擎,它只支持表鎖,并發(fā)寫的時(shí)候,性能差。
  • InnoDB存儲(chǔ)引擎,即支持表鎖,也支持行鎖,默認(rèn)為行級(jí)鎖。
  • BDB 存儲(chǔ)引擎,它支持表鎖和頁鎖。

表級(jí)鎖和行級(jí)鎖的區(qū)別:

  • 表鎖:開銷小,加鎖快;鎖定力度大,發(fā)生鎖沖突概率高,并發(fā)度最低;不會(huì)出現(xiàn)死鎖。
  • 行鎖:開銷大,加鎖慢;會(huì)出現(xiàn)死鎖;鎖定粒度小,發(fā)生鎖沖突的概率低,并發(fā)度高,行級(jí)鎖能大大減少數(shù)據(jù)庫操作的沖突
  • 頁面鎖:開銷和加鎖時(shí)間界于表鎖和行鎖之間;會(huì)出現(xiàn)死鎖;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般。

8. Mysql一條SQL是如何加鎖的?

一條SQL加鎖,可以分9種情況進(jìn)行:

  • 組合一:id 列是主鍵,RC 隔離級(jí)別
  • 組合二:id 列是二級(jí)唯一索引,RC 隔離級(jí)別
  • 組合三:id 列是二級(jí)非唯一索引,RC 隔離級(jí)別
  • 組合四:id 列上沒有索引,RC 隔離級(jí)別
  • 組合五:id 列是主鍵,RR 隔離級(jí)別
  • 組合六:id 列是二級(jí)唯一索引,RR 隔離級(jí)別
  • 組合七:id 列是二級(jí)非唯一索引,RR 隔離級(jí)別
  • 組合八:id 列上沒有索引,RR 隔離級(jí)別
  • 組合九:Serializable 隔離級(jí)別

可以看我這篇文章,第3小節(jié)有詳細(xì)講到哈:兩萬字詳解!InnoDB 鎖專題!

9. 并發(fā)情況下,如何做到安全的修改同一行數(shù)據(jù)

要安全的修改同一行數(shù)據(jù),就要保證一個(gè)線程在修改時(shí)其它線程無法更新這行 記錄。其實(shí)一般有悲觀鎖和樂觀鎖兩種思想,

悲觀鎖思想就是,當(dāng)前線程要進(jìn)來修改數(shù)據(jù)時(shí),別的線程都得拒之門外~ 比如, 可以使用 select…for update ~,

select * from User where name=‘jay’ for update

以上這條 sql 語句會(huì)鎖定了User表中所有符合檢索條件(name=‘jay’)的記 錄。本次事務(wù)提交之前,別的線程都無法修改這些記錄。

還可以使用樂觀鎖思想:

所謂樂觀鎖思想,就是有線程過來,先放過去修改,如果看到別的線程沒修改過, 就可以修改成功,如果別的線程修改過,就修改失敗或者重試。實(shí)現(xiàn)方式:樂 觀鎖一般會(huì)使用版本號(hào)機(jī)制或 CAS 算法實(shí)現(xiàn)??梢钥匆幌挛疫@篇文章,主要是思路哈~ CAS 樂觀鎖解決并發(fā)問題的一次實(shí)踐

當(dāng)然,回答這個(gè)問題的時(shí)候呢,你可以提到分布式鎖。分布式鎖有這三種實(shí)現(xiàn)方式:

  • 數(shù)據(jù)庫分布式鎖
  • Redis分布式鎖
  • Zookeeper分布式鎖

大家可以看我這篇文章哈:面試必備:聊聊分布式鎖的多種實(shí)現(xiàn)!

10. RR隔離級(jí)別下的加鎖規(guī)則是怎么樣的?

其實(shí),極客時(shí)間丁奇的MySQL45講有講到,RR隔離級(jí)別,是如何加鎖的。大家有興趣可以去訂購看下哈,非常不錯(cuò)的課程。

首先MySQL的版本,是5.x 系列 <=5.7.24,8.0 系列 <=8.0.13。加鎖規(guī)則一共包括:兩個(gè)原則、兩個(gè)優(yōu)化和一個(gè)bug。

  • 原則1:加鎖的基本單位都是next-key lock。next-key lock(臨鍵鎖)是前開后閉區(qū)間。
  • 原則2:查找過程中訪問到的對(duì)象才會(huì)加鎖。
  • 優(yōu)化1:索引上的等值查詢,給唯一索引加鎖的時(shí)候,next-key lock退化為行鎖(Record lock)。
  • 優(yōu)化 2:索引上的等值查詢,向右遍歷時(shí)且最后一個(gè)值不滿足等值條件的時(shí)候,next-key lock退化為間隙鎖(Gap lock)。
  • 一個(gè) bug:唯一索引上的范圍查詢會(huì)訪問到不滿足條件的第一個(gè)值為止。

大家可以看我這篇文章,第4小節(jié)有詳細(xì)講到哈:兩萬字詳解!InnoDB 鎖專題!

11. InnoDB 中行級(jí)鎖時(shí)如何實(shí)現(xiàn)的?InnoDB三種行鎖的算法

MySQL上的行級(jí)鎖是通過給索引上的索引項(xiàng)加鎖來實(shí)現(xiàn),只有通過索引條件檢索數(shù)據(jù),InnoDB才使用行級(jí)鎖,否則,InnoDB將使用表鎖。同時(shí),當(dāng)兩條不同行的記錄使用了相同的索引鍵時(shí),也是會(huì)發(fā)生鎖沖突的。

比如這條SQL:

select * from t where id = 666 for update;復(fù)制代碼
for update

可以根據(jù)條件來完成行鎖鎖定,并且 id 是有索引鍵的列,如果 id 不是索引鍵那么InnoDB將實(shí)行表鎖。

InnoDB行鎖的3種算法:

  • Record Lock:單個(gè)索引記錄上的鎖,
  • Gap Lock :間隙鎖,鎖定一個(gè)范圍,但不包含記錄本身
  • Next-Key Lock:它等于Gap Lock + Record Lock,鎖定一個(gè)范圍,并且鎖定記錄本身。

如果查詢條件的是唯一索引,或者主鍵時(shí),Next-Key Lock?會(huì)降為Record Lock?。如果是普通索引,將對(duì)下一個(gè)鍵值加上gap lock?,其實(shí)就是對(duì)下一個(gè)鍵值的范圍為加鎖。gap lock間隙鎖,就是為了解決幻讀問題而設(shè)計(jì)出來的。

間隙鎖是RR隔離級(jí)別的,如果你想關(guān)閉間隙鎖,你可以修改隔離級(jí)別。也可以修改這個(gè)數(shù)據(jù)庫參數(shù)innodb_locks_unsafe_for_binlog為1.

12. MySQL 遇到過死鎖問題嗎,你是如何解決的?

我排查死鎖的一般步驟是醬紫的:

  • 查看死鎖日志show engine innodb status;
  • 找出死鎖Sql
  • 分析sql加鎖情況
  • 模擬死鎖案發(fā)
  • 分析死鎖日志
  • 分析死鎖結(jié)果
責(zé)任編輯:武曉燕 來源: 撿田螺的小男孩
相關(guān)推薦

2023-01-28 08:24:28

MySQL索引B+樹

2024-07-04 11:06:47

2023-04-26 07:40:34

MySQL索引類型存儲(chǔ)

2019-11-18 08:21:04

秒殺系統(tǒng)高性能

2021-11-11 17:34:54

數(shù)據(jù)庫索引面試

2018-07-09 15:27:01

2024-04-29 06:41:04

項(xiàng)目面試官QPS

2011-03-03 13:13:51

DelphiSQLite加密

2022-03-29 10:52:08

MySQL數(shù)據(jù)庫

2018-10-16 16:00:39

數(shù)據(jù)庫鎖舞MySQL

2018-02-27 15:48:31

數(shù)據(jù)庫SQL鎖死

2010-06-07 13:30:15

2019-08-19 14:47:28

數(shù)據(jù)庫軟件技術(shù)

2019-12-12 14:52:10

數(shù)據(jù)庫腳本

2011-08-18 13:44:42

Oracle悲觀鎖樂觀鎖

2019-12-04 09:05:15

千萬級(jí)流量高并發(fā)

2024-01-08 08:15:57

數(shù)據(jù)庫優(yōu)化內(nèi)存

2010-06-29 17:10:22

SQL Server數(shù)

2015-05-19 17:04:28

桌面云如風(fēng)達(dá)深信服

2010-04-22 09:42:00

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)