上一篇文章[MySQL系列之一 -- 事務(wù)](http://www.reibang.com/p/5b213becd8ad)
中在介紹事務(wù)的隔離等級實(shí)現(xiàn)原理是引入了MySQL鎖的機(jī)制,本篇文章就針對MySQL鎖的機(jī)制來做下簡單介紹,總的來說碰辅,InnoDB共有七種類型的鎖:
- 自增鎖(Auto-inc Locks)
- 共享/排它鎖(Shared and Exclusive Locks)
- 意向鎖(Intention Locks)
- 插入意向鎖(Insert Intention Locks)
- 記錄鎖(Record Locks)
- 間隙鎖(Gap Locks)
- 臨鍵鎖(Next-key Locks)
1. 自增鎖(Auto-inc Locks)
說明
自增鎖是一種特殊的表級別鎖(table-level lock)蚁阳,專門針對事務(wù)插入AUTO_INCREMENT類型的列瞳收。
最簡單的情況惊完,如果一個事務(wù)正在往表中插入記錄稽莉,所有其他事務(wù)的插入必須等待溅话,以便第一個事務(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._
與此同時飞几,InnoDB提供了innodb_autoinc_lock_mode配置砚哆,可以調(diào)節(jié)與改變該鎖的模式與行為。
2. 共享/排它鎖(Shared and Exclusive Locks)
- 事務(wù)拿到某一行記錄的共享S鎖,才可以讀取這一行躁锁;多個事務(wù)可以拿到一把S鎖纷铣,讀讀可以并行;
- 事務(wù)拿到某一行記錄的排它X鎖战转,才可以修改或者刪除這一行搜立;只有一個事務(wù)可以拿到X鎖,寫寫/讀寫必須互斥槐秧;
- 兼容互斥表如下:
S X
S 兼容 互斥
X 互斥 互斥
3 意向鎖(Intention Locks)
意向鎖是指啄踊,未來的某個時刻,事務(wù)可能要加共享/排它鎖了刁标,先提前聲明一個意向颠通。
InnoDB支持多粒度鎖(multiple granularity locking),它允許行級鎖與表級鎖共存膀懈,實(shí)際應(yīng)用中顿锰,InnoDB使用的是意向鎖。
意向鎖有這樣一些特點(diǎn):
(1)首先启搂,意向鎖硼控,是一個表級別的鎖(table-level locking);
(2)意向鎖分為:
- 意向共享鎖(intention shared lock, IS)胳赌,它預(yù)示著牢撼,事務(wù)有意向?qū)Ρ碇械哪承┬屑庸蚕鞸鎖
- 意向排它鎖(intention exclusive lock, IX),它預(yù)示著疑苫,事務(wù)有意向?qū)Ρ碇械哪承┬屑优潘黊鎖
舉個例子:
select ... lock in share mode浪默,要設(shè)置IS鎖;
select ... for update缀匕,要設(shè)置IX鎖;
(3)意向鎖協(xié)議(intention locking protocol)并不復(fù)雜:
- 事務(wù)要獲得某些行的S鎖碰逸,必須先獲得表的IS鎖
- 事務(wù)要獲得某些行的X鎖乡小,必須先獲得表的IX鎖
(4)由于意向鎖僅僅表明意向,它其實(shí)是比較弱的鎖饵史,意向鎖之間并不相互互斥满钟,而是可以并行,其兼容互斥表如下:
IS IX
IS 兼容 兼容
IX 兼容 兼容
(5)額胳喷,既然意向鎖之間都相互兼容湃番,那其意義在哪里呢?它會與共享鎖/排它鎖互斥吭露,其兼容互斥表如下:
S X
IS 兼容 互斥
IX 互斥 互斥
畫外音:排它鎖是很強(qiáng)的鎖吠撮,不與其他類型的鎖兼容。這也很好理解讲竿,修改和刪除某一行的時候泥兰,必須獲得強(qiáng)鎖弄屡,禁止這一行上的其他并發(fā),以保障數(shù)據(jù)的一致性鞋诗。
4插入意向鎖(Insert Intention Locks)
插入意向鎖膀捷,是間隙鎖(Gap Locks)的一種(所以,也是實(shí)施在索引上的)削彬,它是專門針對insert操作的全庸。InnoDB使用插入意向鎖,可以提高插入并發(fā)融痛;
對已有數(shù)據(jù)行的修改與刪除壶笼,必須加強(qiáng)互斥鎖X鎖,那對于數(shù)據(jù)的插入酌心,是否還需要加這么強(qiáng)的鎖拌消,來實(shí)施互斥呢?插入意向鎖安券,孕育而生墩崩。
它的核心是:
多個事務(wù),在同一個索引侯勉,同一個范圍區(qū)間插入記錄時鹦筹,如果插入的位置不沖突,不會阻塞彼此址貌。
_Insert Intention Lock signals the intent to insert in such a way that multiple transactions
inserting into the same index gap need not wait for each other if they are not inserting at the
same position within the gap._
- 雖然事務(wù)隔離級別是RR铐拐,雖然是同一個索引,雖然是同一個區(qū)間练对,但插入的記錄并不沖突遍蟋,則使用的是插入意向鎖, 并不會阻塞事務(wù)B
5 記錄鎖(Record Locks)
記錄鎖,它封鎖索引記錄螟凭。例如:
select * from t where id=1 for update;
它會在id=1的索引記錄上加鎖虚青,以阻止其他事務(wù)插入,更新螺男,刪除id=1的這一行棒厘。
注意:
select * from t where id=1;
是快照讀(SnapShot Read),它并不加鎖.
另: RC級別下下隧,采用記錄鎖奢人,解決臟讀問題,但是會出現(xiàn)幻讀淆院,以及不可重復(fù)讀何乎。
6 間隙鎖(Gap Locks)
間隙鎖,它封鎖索引記錄中的間隔,或者第一條索引記錄之前的范圍宪赶,又或者最后一條索引記錄之后的范圍宗弯。
間隙鎖的主要目的,就是為了防止其他事務(wù)在間隔中插入數(shù)據(jù)搂妻,以導(dǎo)致“不可重復(fù)讀”蒙保。
例如:
select * from t
where id between 8 and 15
for update;
注意: 如果把事務(wù)的隔離級別降級為讀提交(Read Committed, RC),間隙鎖則會自動失效欲主,所以間隙鎖對應(yīng)的隔離級別是RR邓厕。
另: RR級別下其實(shí)Next-Key Lock的方式對數(shù)據(jù)行進(jìn)行加鎖,并不是僅僅使用間隙鎖扁瓢。
臨鍵鎖(Next-Key Locks)
臨鍵鎖详恼,是記錄鎖與間隙鎖的組合,它的封鎖范圍引几,既包含索引記錄昧互,又包含索引區(qū)間。
臨鍵鎖的主要目的伟桅,也是為了避免幻讀(Phantom Read)敞掘。如果把事務(wù)的隔離級別降級為RC,臨鍵鎖則也會失效楣铁。
默認(rèn)情況下玖雁,InnoDB工作在可重復(fù)讀(Repeatable Read)隔離級別下,并且會以Next-Key Lock的方式對數(shù)據(jù)行進(jìn)行加鎖盖腕,這樣可以有效防止幻讀的發(fā)生赫冬。Next-Key Lock是行鎖和間隙鎖的組合,當(dāng)InnoDB掃描索引記錄的時候溃列,會首先對索引記錄加上行鎖(Record Lock)劲厌,再對索引記錄兩邊的間隙加上間隙鎖(Gap Lock)。加上間隙鎖之后听隐,其他事務(wù)就不能在這個間隙修改或者插入記錄脊僚。