mysql 行鎖

InnoDB的行鎖按鎖的互斥程度來劃分

Shared Lock 共享鎖(s):又稱讀鎖。

  • 允許一個事務(wù)去讀一行,阻止其他事務(wù)獲得相同數(shù)據(jù)集的排他鎖。–讀鎖
  • 顯式加鎖
select * from test lock in share mode;

Exclusive Lock 排他鎖(X):又稱寫鎖。

  • 允許獲取排他鎖的事務(wù)更新數(shù)據(jù)既穆,阻止其他事務(wù)取得相同的數(shù)據(jù)集共享讀鎖和排他寫鎖赎懦。–寫鎖

  • 對于UPDATE、DELETE和INSERT語句幻工,InnoDB會自動給涉及及數(shù)據(jù)集加排他鎖(X)励两;對于普通SELECT語句,InnoDB不會加任務(wù)鎖囊颅;

  • 顯式加鎖
select * from test for update;

無鎖当悔、S鎖、X鎖的互斥情況試驗

鎖類型 lock in share mode for update
select 兼容 兼容
lock in share mode 兼容 互斥
for update 互斥 互斥

為了節(jié)省時間踢代,x鎖我統(tǒng)一使用select … for update的方式

S鎖的互斥情況
image.png
X鎖的互斥情況
image.png

S鎖和X鎖的注意事項

image.png

如果事務(wù)A使用select ... lock in share mode 的話盲憎,之后事務(wù)B也使用select ... lock in share mode。這樣事務(wù)B持鎖胳挎,然后在事務(wù)A里執(zhí)行update語句會造成死鎖饼疙;對于鎖定記錄后需要進(jìn)行更新操作的應(yīng)用,應(yīng)該使用select ... for update 的方式獲得排它鎖慕爬。

InnoDB行鎖實現(xiàn)方式

  • 在不通過索引條件查詢時宏多,InnoDB會鎖定表中的所有記錄!


    image.png
  • mysql的行鎖是針對索引加鎖澡罚,不是針對記錄加鎖,所以雖然是訪問到不同的記錄肾请,但是使用相同的索引鍵(使用普通索引而非唯一索引)留搔,是會出現(xiàn)鎖沖突的
    在這里id是普通的索引


    image.png
  • 當(dāng)表有多個索引的時候,不同的事務(wù)可以使用的索引鎖定不同的行铛铁,不論是使用主鍵索引隔显、唯一索引或普通索引,InnoDB都會使用行鎖來對數(shù)據(jù)加鎖饵逐。


    image.png
  • 在查詢中索引不一定會被用到括眠,這個時候就會進(jìn)行全表掃描,形成表鎖


    image.png

InnoDB行鎖按實現(xiàn)方案可以分3種:

  • 默認(rèn)情況下倍权,InnoDB工作在RR隔離級別下掷豺,并且以Next-Key Lock的方式對數(shù)據(jù)行進(jìn)行加鎖。

  • Next-Key Lock是行鎖與間隙鎖的組合薄声,這樣当船,當(dāng)InnoDB掃描索引記錄的時候,會首先對選中的索引記錄加上行鎖(Record Lock)默辨,再對索引記錄兩邊的間隙(向左掃描掃到第一個比給定參數(shù)小的值德频, 向右掃描掃描到第一個比給定參數(shù)大的值, 然后以此為界缩幸,構(gòu)建一個區(qū)間)加上間隙鎖(Gap Lock)壹置。

  • 如果一個間隙被事務(wù)A加了鎖竞思,其它事務(wù)是不能在這個間隙插入記錄的。

Record lock:

  • 記錄鎖钞护,對索引項加鎖

Gap lock:

  • 間隙鎖盖喷,鎖加在不存在的空閑空間,可以是兩個索引記錄之間患亿,也可能是第一個索引記錄之前或最后一個索引之后的空間传蹈。
  • 關(guān)閉間隙鎖:可以通過修改隔離級別為 READ COMMITTED 或者配置 innodb_locks_unsafe_for_binlog 參數(shù)為 ON。
    mysql5.6中不能通過命令直接設(shè)置步藕,表示這個參數(shù)是只讀的惦界。只能通過修改my.cnf文件后重啟
set @@innodb_locks_unsafe_for_binlog = ON
image.png
  • 間隙鎖在RR級別下開啟
  • 間隙鎖會對 在不存在的記錄上做insert操作 加鎖
  • 間隙鎖驗證


    image.png

    image.png
  • 當(dāng)操作作用于 不存在的一條記錄 時也會出現(xiàn)間隙鎖,驗證如下:
    以update為主
    image.png

以select .. for update為主


image.png

以insert為主


image.png

以delete為主


image.png

id=15的記錄并不存在

鎖類型 select * from test where id = 15 for update; delete from test where id = 15; update test set a='fff' where id =15; INSERT INTO test(id, a, b, c) VALUES (15, 'new !!!!', 'bbb', 'ccc');
select * from test where id = 15 for update; 兼容 兼容 兼容 互斥
delete from test where id = 15; 兼容 兼容 兼容 互斥
update test set a='fff' where id =15; 兼容 兼容 兼容 互斥
INSERT INTO test(id, a, b, c) VALUES (15, 'new !!!!', 'bbb', 'ccc'); 互斥 互斥 互斥 互斥
  • 在RC下驗證間隙鎖關(guān)閉情況
    image.png

    RC下間隙鎖的確是關(guān)閉的咙冗。如果事務(wù)B提交后沾歪。事務(wù)A繼續(xù)執(zhí)行一個查詢操作∥硐可以發(fā)現(xiàn)多處了一條記錄灾搏。出現(xiàn)了幻讀
    image.png
  • 我在這里有兩個問題很不解:
    1立润、《高性能mysql》說MVCC機(jī)制在RC和RR下生效狂窑,那為什么不能杜絕RC下的幻讀?
    答:因為RC下和RR下MVCC機(jī)制不同桑腮,RC下每次select都會生成readview泉哈,而RR下只在第一次select生成readview
    2、RC下因為沒有間隙鎖機(jī)制而出現(xiàn)了幻讀破讨。那MVCC機(jī)制解決幻讀和間隙鎖解決的幻讀是不是一個概念丛晦?
    答:RR下的MVCC能解決幻讀是:普通select快照讀;RR下間隙鎖解決的幻讀是:select ... lock in share mode提陶、select .. for update的加鎖讀
  • 間隙鎖的危害


    image.png

Next-key lock:

  • 臨鍵鎖烫沙,該鎖就是 Record Locks 和 Gap Locks 的組合,即鎖定一個范圍并且鎖定該記錄本身
  • 舉個例子隙笆,如果一個索引有 1, 3, 5 三個值锌蓄,則該索引鎖定的區(qū)間為 (-∞,1], (1,3], (3,5], (5,+ ∞) 前開后閉區(qū)間

查看行鎖情況

show status like 'InnoDB_row_lock%';
image.png

對于各個字段說明如下:

  • Innodb_row_lock_current_waits:當(dāng)前正在等待鎖的數(shù)量;
  • Innodb_row_lock_time:從系統(tǒng)啟動到現(xiàn)在鎖定總時間長度撑柔;
  • Innodb_row_lock_time_avg:每次等待所花平均時間煤率;
  • Innodb_row_lock_time_max:從系統(tǒng)啟動到現(xiàn)在等待最長的一次所花的時間長度;
  • Innodb_row_lock_waits:系統(tǒng)啟動到現(xiàn)在總共等待的次數(shù)乏冀;
    如果發(fā)現(xiàn)鎖爭用比較嚴(yán)重蝶糯,還可以通過設(shè)置InnoDB Monitors 來進(jìn)一步觀察發(fā)生鎖沖突的表、數(shù)據(jù)行等辆沦,并分析鎖爭用的原因昼捍。

注意识虚,這條sql無法查詢到持鎖數(shù)量和鎖類型。只有在引發(fā)阻塞后才會記錄鎖的信息妒茬。在mysql5.7中請使用show engine innodb status;來獲得這兩個信息担锤!

關(guān)于行鎖的優(yōu)化建議

  • 盡可能讓所有數(shù)據(jù)檢索都通過索引來完成,避免無索引行鎖升級為表鎖
  • 合理設(shè)計索引乍钻,盡量縮小鎖的范圍
  • 盡可能較少檢索條件肛循,避免間隙鎖
  • 盡量控制事務(wù)大小,減少鎖定資源量和時間長度
  • 盡可能低級別事務(wù)隔離
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末银择,一起剝皮案震驚了整個濱河市多糠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌浩考,老刑警劉巖夹孔,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異析孽,居然都是意外死亡搭伤,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進(jìn)店門袜瞬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來怜俐,“玉大人,你說我怎么就攤上這事邓尤∨睦穑” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵裁赠,是天一觀的道長。 經(jīng)常有香客問我赴精,道長佩捞,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任蕾哟,我火速辦了婚禮一忱,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘谭确。我一直安慰自己帘营,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布逐哈。 她就那樣靜靜地躺著芬迄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪昂秃。 梳的紋絲不亂的頭發(fā)上禀梳,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天杜窄,我揣著相機(jī)與錄音,去河邊找鬼算途。 笑死塞耕,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的嘴瓤。 我是一名探鬼主播扫外,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼廓脆!你這毒婦竟也來了筛谚?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤狞贱,失蹤者是張志新(化名)和其女友劉穎刻获,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體瞎嬉,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蝎毡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了氧枣。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沐兵。...
    茶點故事閱讀 38,814評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖便监,靈堂內(nèi)的尸體忽然破棺而出扎谎,到底是詐尸還是另有隱情,我是刑警寧澤烧董,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布毁靶,位于F島的核電站,受9級特大地震影響逊移,放射性物質(zhì)發(fā)生泄漏预吆。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一胳泉、第九天 我趴在偏房一處隱蔽的房頂上張望拐叉。 院中可真熱鬧,春花似錦扇商、人聲如沸凤瘦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蔬芥。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間坝茎,已是汗流浹背涤姊。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留嗤放,地道東北人思喊。 一個月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像次酌,于是被迫代替她去往敵國和親恨课。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,728評論 2 351