這篇文章給大家介紹MySQL中怎么實(shí)現(xiàn) innodb鎖機(jī)制,內(nèi)容非常詳細(xì),感興趣的小伙伴們可以參考借鑒,希望對(duì)大家能有所幫助。
成都創(chuàng)新互聯(lián)公司一直在為企業(yè)提供服務(wù),多年的磨煉,使我們?cè)趧?chuàng)意設(shè)計(jì),網(wǎng)絡(luò)營銷推廣到技術(shù)研發(fā)擁有了開發(fā)經(jīng)驗(yàn)。我們擅長傾聽企業(yè)需求,挖掘用戶對(duì)產(chǎn)品需求服務(wù)價(jià)值,為企業(yè)制作有用的創(chuàng)意設(shè)計(jì)體驗(yàn)。核心團(tuán)隊(duì)擁有超過十多年以上行業(yè)經(jīng)驗(yàn),涵蓋創(chuàng)意,策化,開發(fā)等專業(yè)領(lǐng)域,公司涉及領(lǐng)域有基礎(chǔ)互聯(lián)網(wǎng)服務(wù)成都服務(wù)器托管、App定制開發(fā)、手機(jī)移動(dòng)建站、網(wǎng)頁設(shè)計(jì)、網(wǎng)絡(luò)整合營銷。
InnoDB實(shí)現(xiàn)標(biāo)準(zhǔn)的行級(jí)鎖定,其中有兩種類型的鎖定:共享鎖(S)和排他鎖(X)。
1)共享鎖允許持有該鎖的事務(wù)讀取一行數(shù)據(jù)。
2)排他鎖允許持有該鎖的事務(wù)更新或刪除一行數(shù)據(jù)。
如果事務(wù)T1在行r上持有一個(gè)共享鎖(S),那么來自其他不同事務(wù)T2的對(duì)行r上的鎖的請(qǐng)求將按以下方式處理:
1)T2可以立即獲得行r的共享鎖,T1和T2都在r上保持了S鎖。
2)T2不能立即獲取到排它鎖。
如果事務(wù)T1在行r上持有排他(X)鎖,則不能立即批準(zhǔn)某個(gè)不同事務(wù)T2對(duì)r上任一類型的鎖的請(qǐng)求。 相反,事務(wù)T2必須等待事務(wù)T1釋放對(duì)行r的鎖定。
InnoDB支持多種粒度鎖定,允許行鎖和表鎖并存。 例如,諸如LOCK TABLES ... WRITE之類的語句對(duì)指定表采用排他鎖(X鎖)。 但是有一個(gè)問題,如果一個(gè)事務(wù)對(duì)一張表的某條數(shù)據(jù)進(jìn)行加鎖,這個(gè)時(shí)候如果有另外一個(gè)線程想要用LOCK TABLES進(jìn)行鎖表,這時(shí)候數(shù)據(jù)庫要怎么知道哪張表的哪條數(shù)據(jù)被加了鎖,一張張表一條條數(shù)據(jù)去遍歷是不可行的。 為了使在多個(gè)粒度級(jí)別上的鎖定變得切實(shí)可行,InnoDB使用了意圖鎖定。 意向鎖是表級(jí)鎖,指示事務(wù)稍后對(duì)表中的行需要哪種類型的鎖(共享鎖或排他鎖)。
有兩種類型的意圖鎖:
1)意向共享鎖(IS)表示事務(wù)打算對(duì)表中的各個(gè)行設(shè)置共享鎖。
2)意向排他鎖(IX)表示事務(wù)打算對(duì)表中的各個(gè)行設(shè)置排他鎖。
例如,SELECT ... LOCK IN SHARE MODE設(shè)置IS鎖定,而SELECT ... FOR UPDATE設(shè)置IX鎖定。
意向鎖定協(xié)議如下:
1)事務(wù)在獲取表中某行的共享鎖之前,它必須首先獲取該表中的IS鎖或更強(qiáng)的鎖。
2)事務(wù)在獲取表中某行的排它鎖之前,它必須首先獲取該表中的IX鎖。
表級(jí)鎖類型的兼容性匯總在以下矩陣中:
X | IX | S | IS | |
X | 沖突 | 沖突 | 沖突 | 沖突 |
IX | 沖突 | 兼容 | 沖突 | 兼容 |
S | 沖突 | 沖突 | 兼容 | 兼容 |
IS | 沖突 | 兼容 | 兼容 | 兼容 |
如果一個(gè)鎖與現(xiàn)有鎖兼容,則將其授予請(qǐng)求的事務(wù),但如果與現(xiàn)有鎖沖突,則不授予該鎖。 事務(wù)等待直到?jīng)_突的現(xiàn)有鎖被釋放。 如果鎖定請(qǐng)求與現(xiàn)有鎖定發(fā)生沖突,并且由于可能導(dǎo)致死鎖而無法被授予,則會(huì)發(fā)生錯(cuò)誤。
意向鎖除了全表請(qǐng)求(例如LOCK TABLES ... WRITE)外,不阻止任何其他內(nèi)容。 意圖鎖定的主要目的是表明某人正在鎖定表中的行或要鎖定表中的行。
在SHOW ENGINE INNODB STATUS和InnoDB監(jiān)視器輸出中,意圖鎖定的事務(wù)數(shù)據(jù)看起來類似于以下內(nèi)容:
TABLE LOCK table `test`.`t` trx id 10080 lock mode IX
記錄鎖定是對(duì)索引記錄的鎖定。 例如,SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE; 防止任何其他事務(wù)插入,更新或刪除t.c1值為10的行。記錄鎖始終鎖定索引記錄,即使沒有定義索引的表也是如此。 對(duì)于這種情況,InnoDB創(chuàng)建一個(gè)隱藏的聚集索引,并將該索引用于記錄鎖定。
記錄鎖定的事務(wù)數(shù)據(jù)在SHOW ENGINE INNODB STATUS和InnoDB監(jiān)視器輸出中看起來類似于以下內(nèi)容:
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 ;;
間隙鎖是對(duì)索引記錄之間的間隙的鎖定,或者是對(duì)第一個(gè)或最后一個(gè)索引記錄之前的間隙的鎖定。例如:SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;防止其他事務(wù)將10到20之間的值插入到t.c1的列上,無論該列中是否已經(jīng)存在這樣的值,因?yàn)樵摲秶鷥?nèi)所有現(xiàn)有值之間的間隙是鎖定的。
間隙可能跨越單個(gè)索引值,多個(gè)索引值,甚至為空。間隙鎖是性能和并發(fā)性之間權(quán)衡的一部分,并且在某些事務(wù)隔離級(jí)別而非其他級(jí)別中使用。
對(duì)于查詢唯一行的語句時(shí),鎖定行時(shí)使用唯一索引,不需要間隙鎖定。 (這不包括搜索條件僅包含多列唯一索引的某些列的情況;在這種情況下,會(huì)發(fā)生間隙鎖定。)例如,如果id列具有唯一索引,則以下語句僅使用 ID值為100的行的索引記錄鎖,其他會(huì)話是否在前面的間隙中插入行都沒有關(guān)系:
SELECT * FROM child WHERE id = 100;
如果id未建立索引或具有非唯一索引,則該語句會(huì)鎖定前面的間隙。
在這里還值得注意的是,可以通過不同的事務(wù)將沖突的鎖保持在間隙上。 例如,事務(wù)A可以在間隙上保留一個(gè)共享的間隙鎖(間隙S鎖),而事務(wù)B可以在同一間隙上保留排他的間隙鎖(間隙X鎖)。允許沖突的間隙鎖的原因是,如果從索引中清除記錄,則必須合并由不同事務(wù)保留在記錄上的間隙鎖。
InnoDB中的間隙鎖唯一目的是防止其他事務(wù)插入間隙。 間隙鎖可以共存。 一個(gè)事務(wù)進(jìn)行的間隙鎖定不會(huì)阻止另一事務(wù)對(duì)相同的間隙進(jìn)行間隙鎖定。 共享間隙鎖和排他間隙鎖之間沒有區(qū)別。 它們彼此不沖突,并且執(zhí)行相同的功能。
間隙鎖定可以顯式禁用。 如果將事務(wù)隔離級(jí)別更改為READ COMMITTED或啟用innodb_locks_unsafe_for_binlog系統(tǒng)變量(現(xiàn)已棄用),則會(huì)發(fā)生這種情況。 在這種情況下,將禁用間隙鎖定進(jìn)行搜索和索引掃描,并且僅將其用于外鍵約束檢查和重復(fù)鍵檢查。
Next-Key Lock是索引記錄上的記錄鎖定和索引記錄之前的間隙上的間隙鎖定的組合,即記錄鎖和間隙鎖的組合。
InnoDB執(zhí)行行級(jí)鎖定的方式是,當(dāng)它搜索或掃描表索引時(shí),會(huì)在遇到的索引記錄上設(shè)置共享或互斥鎖。 因此,行級(jí)鎖實(shí)際上是索引記錄鎖。 索引記錄上的next-key lock也會(huì)影響該索引記錄之前的“間隙”。 即,next-key lock是索引記錄鎖定加上索引記錄之前的間隙上的間隙鎖定。 如果一個(gè)會(huì)話在索引中的記錄R上具有共享或排他鎖,則另一會(huì)話不能按照索引順序在R之前的間隙中插入新的索引記錄。
假設(shè)索引包含值10、11、13和20。此索引的可能的next-key lock涵蓋以下間隔,其中,圓括號(hào)表示排除區(qū)間端點(diǎn),方括號(hào)表示包括端點(diǎn):
(-∞, 10] (10, 11] (11, 13] (13, 20] (20, +∞)
對(duì)于最后一個(gè)間隔,next-key lock將間隙鎖定在索引中的最大值上方,此next-key lock僅鎖定最大索引值之后的間隙。
默認(rèn)情況下,InnoDB以REPEATABLE READ事務(wù)隔離級(jí)別運(yùn)行。 在這種情況下,InnoDB使用next-key lock進(jìn)行搜索和索引掃描,這可以防止幻讀問題。
next-key lock的事務(wù)數(shù)據(jù)在SHOW ENGINE INNODB STATUS和InnoDB監(jiān)視器輸出中看起來類似于以下內(nèi)容:
RECORD LOCKS space id 58 page no 3 n bits 72 index `PRIMARY` of table `test`.`t` trx id 10080 lock_mode X Record lock, heap no 1 PHYSICAL RECORD: n_fields 1; compact format; info bits 0 0: len 8; hex 73757072656d756d; asc supremum;; 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 ;;
插入意圖鎖定是一種在行插入之前通過INSERT操作設(shè)置的間隙鎖定的類型。 此鎖發(fā)出插入意圖的信號(hào)是,在同一個(gè)索引間隙中,如果多個(gè)事務(wù)未插入間隙中的相同位置,則無需等待插入到同一索引間隙中的多個(gè)事務(wù)。 假設(shè)有索引記錄,其值分別為4和7。單獨(dú)的事務(wù)分別嘗試插入值5和6,在獲得插入行的排他鎖之前,每個(gè)事務(wù)都使用插入意圖鎖來鎖定4和7之間的間隙,但不要互相阻塞,因?yàn)樾惺菬o沖突的。
下面的示例演示了在獲得對(duì)插入記錄的排他鎖之前,使用插入意圖鎖的事務(wù)。 該示例涉及兩個(gè)客戶端A和B。
客戶端A創(chuàng)建一個(gè)包含兩個(gè)索引記錄(90和102)的表,然后啟動(dòng)一個(gè)事務(wù),該事務(wù)將排他鎖放置在ID大于100的索引記錄上。排他鎖在記錄102之前包括一個(gè)間隙鎖:
mysql> CREATE TABLE child (id int(11) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB; mysql> INSERT INTO child (id) values (90),(102); mysql> START TRANSACTION; mysql> SELECT * FROM child WHERE id > 100 FOR UPDATE; +-----+ | id | +-----+ | 102 | +-----+
客戶B開始交易以將記錄插入空白。 事務(wù)在等待獲得排他鎖的同時(shí)獲取插入意圖鎖。
mysql> START TRANSACTION; mysql> INSERT INTO child (id) VALUES (101);
插入意圖鎖定的事務(wù)數(shù)據(jù)在SHOW ENGINE INNODB STATUS和InnoDB監(jiān)視器輸出中看起來類似于以下內(nèi)容:
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 ;;...
AUTO-INC鎖是一種特殊的表級(jí)鎖,由插入到具有AUTO_INCREMENT列的表中的事務(wù)獲取。 在最簡(jiǎn)單的情況下,如果一個(gè)事務(wù)正在向表中插入值,則任何其他事務(wù)都必須等待自己在該表中進(jìn)行插入,以便第一個(gè)事務(wù)插入的行接收連續(xù)的主鍵值。
innodb_autoinc_lock_mode配置選項(xiàng)控制用于自動(dòng)增量鎖定的算法。 它使您可以選擇如何在可預(yù)測(cè)的自動(dòng)增量值序列與插入操作的最大并發(fā)性之間進(jìn)行權(quán)衡。
InnoDB支持包含空間列的列的空間索引,要處理涉及SPATIAL索引的操作的鎖定,next-key lock不能很好地支持REPEATABLE READ或SERIALIZABLE事務(wù)隔離級(jí)別。 多維數(shù)據(jù)中沒有絕對(duì)排序概念,因此不清楚哪個(gè)是next key。
為了支持具有SPATIAL索引的表的隔離級(jí)別,InnoDB使用predicate locks。 SPATIAL索引包含最小邊界矩形(MBR)值,因此InnoDB通過在用于查詢的MBR值上設(shè)置謂詞鎖定來強(qiáng)制對(duì)索引進(jìn)行一致的讀取。 其他事務(wù)不能插入或修改將匹配查詢條件的行。
關(guān)于mysql中怎么實(shí)現(xiàn) innodb鎖機(jī)制就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。