mysql鎖

  • 對于UPDATE芜赌、DELETE仰挣、INSERT語句,InnoDB會自動給涉及數(shù)據(jù)集加排他鎖(X)
  • InnoDB行鎖和表鎖都支持较鼓!
    表鎖:開銷小椎木,加鎖快;不會出現(xiàn)死鎖博烂;鎖定力度大,發(fā)生鎖沖突概率高漱竖,并發(fā)度最低
    行鎖:開銷大禽篱,加鎖慢;會出現(xiàn)死鎖馍惹;鎖定粒度小躺率,發(fā)生鎖沖突的概率低玛界,并發(fā)度高
  • InnoDB只有通過索引條件檢索數(shù)據(jù)才使用行級鎖,否則悼吱,InnoDB將使用表鎖
  • InnoDB行鎖是通過索引上的索引項來實現(xiàn)的慎框,這一點MySQL與Oracle不同,后者是通過在數(shù)據(jù)中對相應(yīng)數(shù)據(jù)行加鎖來實現(xiàn)的后添。
  • InnoDB實現(xiàn)了以下兩種類型的行鎖:共享鎖(S鎖笨枯、讀鎖),排他鎖(X鎖遇西,寫鎖)
    共享鎖:一個事務(wù)去讀一行數(shù)據(jù)馅精,給這行數(shù)據(jù)加上共享鎖,此時其他事務(wù)也可以讀取這行數(shù)據(jù)粱檀,同樣加上共享鎖(讀讀不沖突)洲敢。但是不可以去修改(update,delete)這條數(shù)據(jù),因為修改加的是排他鎖茄蚯,共享鎖之上不可以加排他鎖(讀寫沖突)压彭。
    排他鎖:一個事務(wù)去修改一行數(shù)據(jù),給這行數(shù)據(jù)加上排他鎖渗常,此時其他事務(wù)不可以讀取這行數(shù)據(jù)哮塞,也不可以修改這行數(shù)據(jù)(寫讀沖突,寫寫沖突)凳谦。
  • 數(shù)據(jù)庫事務(wù)有不同的隔離級別忆畅,不同的隔離級別對鎖的使用是不同的。MySQL默認使用的可重復(fù)讀的隔離級別 , 可重復(fù)讀會導(dǎo)致幻讀 , 通過mvvc和gap鎖解決了幻讀(
    參考: https://my.oschina.net/u/566591/blog/3162858?_from=gitee_rec )尸执。其中mvvc是讀寫不阻塞的
  • MySQL對于UPDATE家凯、DELETE、INSERT語句, 都會加鎖, 導(dǎo)致其他的SQL語句阻塞( 也就是寫寫阻塞 ), 在高并發(fā)的情況下, 雖然保證了數(shù)據(jù)安全 , 但是數(shù)據(jù)庫會承受大量的IO操作, 大量的操作就會阻塞, 可能會導(dǎo)致宕機等, 所以需要緩沖這些服務(wù), 可以使用MQ來異步操作
1. select * from my_table where id = 1;
2. select * from my_table where id = 1 lock in share mode;
3. select * from my_table where id = 1 for update;
4. update my_table set address = 'tianjin' where id = 1;
先說隔離級別如失,mysql隔離級別分為四種:
未提交讀(read uncommitted)绊诲、提交讀(read committed)、重復(fù)讀(repeatable read)褪贵、序列化(serializable)
其中mysql默認的隔離級別為重復(fù)讀(repeatable read)掂之,以下簡稱為rr,本文也只介紹這種模式
讀的模式分為兩種:
快照讀(snapshot read)
當(dāng)前讀(current read)
我們先來了解一下MVCC:
MVCC是為了實現(xiàn)數(shù)據(jù)庫的并發(fā)控制而設(shè)計的一種協(xié)議脆丁。與其相對的事LBCC即基于鎖的并發(fā)控制(Lock-Based Concurrent Control)世舰。要實現(xiàn)數(shù)據(jù)庫的并發(fā)訪問控制,最簡單的做法就是加鎖訪問槽卫,即讀的時候不能寫(這個讀為當(dāng)前讀跟压,后面介紹。允許多個線程同時對想讀的內(nèi)容加鎖歼培,即共享鎖或叫S鎖)震蒋,寫的時候不能讀(只能有一個線程對同一內(nèi)容進行寫操作茸塞,即排它鎖,X鎖)查剖。這樣的加鎖訪問钾虐,其實并不算是真正的并發(fā),或者說它只能實現(xiàn)并發(fā)的讀笋庄,既讀寫串行化效扫,這樣就大大降低了數(shù)據(jù)庫的讀寫性能。
LBCC是四種隔離級別中級別最高的Serialize隔離級別无切。MVCC對比LBCC它的最大好處便是荡短,讀不加鎖,讀寫不沖突哆键。在MVCC中掘托,讀操作可以分成兩類,快照讀(Snapshot read)和當(dāng)前讀(current read)籍嘹∩量快照讀,讀取的是記錄的可見版本(可能是歷史版本辱士,即最新的數(shù)據(jù)可能正在被當(dāng)前執(zhí)行的事務(wù)并發(fā)修改)泪掀,不會對返回的記錄加鎖,如上面的sql語句1颂碘;而當(dāng)前讀异赫,讀取的是記錄的最新版本,并且會對返回的記錄加鎖头岔,保證其他事務(wù)不會并發(fā)修改這條記錄塔拳。如上面的sql語句2,3,4。不同的是2加的是s鎖峡竣,3靠抑、4加的是x鎖,insert加的也是x鎖适掰。
注:MVCC只在RC和RR兩個隔離級別下工作颂碧,其他兩個隔離級別都和MVCC不兼容

快照讀:讀取的是事務(wù)開始時的記錄版本,不會對記錄加鎖类浪。
select * from table where ?
當(dāng)前讀:讀取的是當(dāng)前最新版本载城,并且會對記錄加鎖
select * from table where ? lock in share mode; (加S鎖)
select * from table where ? for update; (加X鎖)
間隙鎖:Gap鎖,顧名思義戚宦,鎖住查詢記錄之間的間隙个曙,只有在RR隔離級下才可以生效,在RC隔離級下無法生效受楼,為了解決mysql幻讀問題垦搬。(非快照讀時解決幻讀方案)
比如有這幾條記錄:0,5艳汽,10猴贰,15,20河狐,25
對于select * from t where id=9米绕,這樣一個不存在行,鎖住的區(qū)間是(5,10); 前開后開
對于select * from t where id=5,這樣存在的行鎖住的是(0,5]這樣的區(qū)間馋艺,其實也就是一個行鎖加一個間隙鎖栅干,就構(gòu)成了一把net-key lock;
net-key lock:行鎖加上間隙鎖

事務(wù)隔離級別對應(yīng)鎖:

  • read uncommited:讀未提交捐祠,事務(wù)b未提交的結(jié)果就被事務(wù)a讀取到了碱鳞,事務(wù)b如果回滾了數(shù)據(jù),事務(wù)a讀取到的數(shù)據(jù)就是臟數(shù)據(jù)(產(chǎn)生臟讀)
    加鎖實現(xiàn):無任何加鎖實現(xiàn)
  • read commited:讀已提交踱蛀,事務(wù)a只能讀取到其他事務(wù)已經(jīng)提交的結(jié)果窿给,避免了臟讀,但是事務(wù)a在兩次查詢之間事務(wù)b修改了此條數(shù)據(jù)率拒,導(dǎo)致事務(wù)a兩次讀取的數(shù)據(jù)不一致的情況崩泡,稱之為(不可重復(fù)讀)。
    加鎖實現(xiàn):mysql之外其他數(shù)據(jù)庫猬膨,讀不加鎖角撞,寫加排他鎖,因為寫加了排他鎖勃痴,所以必須等到寫提交完成并且釋放鎖之后谒所,其他讀寫才能執(zhí)行,所以不會產(chǎn)生臟讀召耘,但是因為讀不加鎖百炬,在同一個事務(wù)兩次讀之間其他事務(wù)依舊可以修改數(shù)據(jù),所以會產(chǎn)生不可重復(fù)讀的結(jié)果污它。
    mysql使用MVCC機制快照讀剖踊,讀寫不沖突,依然會產(chǎn)生不可重復(fù)讀和幻讀衫贬,非快照讀也依舊會有這些問題德澈。
    實操:開2個事務(wù)測試,發(fā)現(xiàn)RC級別不可以解決不可重復(fù)讀和幻讀固惯,但是RR級別都可以解決梆造。
    答案:同樣是使用MVCC機制,為什么處理結(jié)果不一樣呢。是因為InnoDB在設(shè)計上增加了ReadView的設(shè)計镇辉,ReadView中主要包含當(dāng)前系統(tǒng)中還有哪些活躍的讀寫事務(wù)屡穗,生成 ReadView 的時機,RR 級別只在事務(wù)開始時生成一次忽肛,之后一直使用該 ReadView村砂。而 RC 級別則在每次 select 時,都會生成一個 ReadView(rr的事務(wù)級快照屹逛、rc的語句級快照)础废。
  • repeated read:可重復(fù)讀,可以避免不可重復(fù)讀罕模,但是會產(chǎn)生(幻讀)评腺,a事務(wù)查詢一段范圍之間的數(shù)據(jù),b事務(wù)插入了一條這個范圍內(nèi)的數(shù)據(jù)淑掌,a事務(wù)再次查詢發(fā)現(xiàn)多了一條數(shù)據(jù)蒿讥,就像幻覺一樣。
    加鎖實現(xiàn):mysql之外其他數(shù)據(jù)庫锋拖,讀加共享鎖诈悍,寫加排他鎖,因為a事務(wù)在讀的時候就加了共享鎖兽埃,所以其他事務(wù)在a未釋放鎖之前不能加排他鎖去修改數(shù)據(jù)侥钳,所以a在整個事務(wù)之內(nèi)不管查詢多少次數(shù)據(jù)都是一致的,解決不可重復(fù)讀柄错。但是因為加的是行鎖舷夺,b事務(wù)依舊可以在a查詢范圍之內(nèi)去insert一條本來不存在的a未加鎖的數(shù)據(jù),a再次范圍查詢就會發(fā)現(xiàn)多了一條售貌,產(chǎn)生幻讀给猾。
    但是,mysql如果使用MVCC機制快照讀颂跨,就不會產(chǎn)生幻讀敢伸,不使用MVCC機制當(dāng)前讀也不會產(chǎn)生幻讀,因為mysql在這個隔離級別下采用了next-key lock來解決幻讀恒削。
  • serializable:序列化池颈,讀寫全部加鎖,而且是范圍鎖钓丰,解決所有問題躯砰,并發(fā)性能差,擺設(shè)而已携丁?
    備注:只有mysql有MVCC機制琢歇,所以只有mysql可以快照讀。
    備注:MVCC機制只作用于rc和rr級別。
    備注:mysql在rr和rc級別下李茫,使用快照讀都能解決不可重復(fù)讀和幻讀揭保。但是在非快照讀下,rc啥都不能解決涌矢,rr本來就可以解決不可重復(fù)讀掖举,再加上間隙鎖和next-key lock解決幻讀快骗,所以都能解決娜庇,所以實現(xiàn)結(jié)果和serializable一樣。
    備注:只有mysql的rr級別有間隙鎖和next-key lock方篮,所以只有mysql在rr級別可以防止幻讀名秀。
MySQL/InnoDB定義的4種隔離級別:

Read Uncommited
可以讀取未提交記錄。此隔離級別藕溅,不會使用匕得,忽略。

Read Committed (RC)
快照讀忽略巾表,本文不考慮汁掠。

針對當(dāng)前讀,RC隔離級別保證對讀取到的記錄加鎖 (記錄鎖)集币,存在幻讀現(xiàn)象考阱。

Repeatable Read (RR)
快照讀忽略,本文不考慮鞠苟。

針對當(dāng)前讀乞榨,RR隔離級別保證對讀取到的記錄加鎖 (記錄鎖),同時保證對讀取的范圍加鎖当娱,新的滿足查詢條件的記錄不能夠插入 (間隙鎖)吃既,不存在幻讀現(xiàn)象。

Serializable
從MVCC并發(fā)控制退化為基于鎖的并發(fā)控制跨细。不區(qū)別快照讀與當(dāng)前讀鹦倚,所有的讀操作均為當(dāng)前讀,讀加讀鎖 (S鎖)冀惭,寫加寫鎖 (X鎖)震叙。

Serializable隔離級別下,讀寫沖突云头,因此并發(fā)度急劇下降捐友,在MySQL/InnoDB下不建議使用。

ReadView:

row_id :隱藏的行 ID ,用來生成默認的聚集索引溃槐。如果創(chuàng)建數(shù)據(jù)表時沒指定聚集索引匣砖,這時 InnoDB 就會用這個隱藏 ID 來創(chuàng)建聚集索引。采用聚集索引的方式可以提升數(shù)據(jù)的查找效率。
trx_id: 操作這個數(shù)據(jù)事務(wù) ID 猴鲫,也就是最后一個對數(shù)據(jù)插入或者更新的事務(wù) ID 对人。
roll_ptr:回滾指針,指向這個記錄的 Undo Log 信息拂共。

Undo Log
InnoDB 將行記錄快照保存在 Undo Log 里牺弄。

image.png

數(shù)據(jù)行通過快照記錄都通過鏈表的結(jié)構(gòu)的串聯(lián)了起來,每個快照都保存了 trx_id 事務(wù)ID宜狐,如果要找到歷史快照势告,就可以通過遍歷回滾指針的方式進行查找。
如果一個事務(wù)要查詢行記錄抚恒,需要讀取哪個版本的行記錄呢咱台? Read View 就是來解決這個問題的。Read View 可以幫助我們解決可見性問題俭驮。 Read View 保存了當(dāng)前事務(wù)開啟時所有活躍的事務(wù)列表回溺。換個角度,可以理解為: Read View 保存了不應(yīng)該讓這個事務(wù)看到的其他事務(wù) ID 列表混萝。

trx_ids 系統(tǒng)當(dāng)前正在活躍的事務(wù)ID集合遗遵。
low_limit_id ,活躍事務(wù)的最大的事務(wù) ID。
up_limit_id 活躍的事務(wù)中最小的事務(wù) ID逸嘀。
creator_trx_id车要,創(chuàng)建這個 ReadView 的事務(wù)ID。

image.png

如果當(dāng)前事務(wù)的 creator_trx_id 想要讀取某個行記錄厘熟,這個行記錄ID 的trx_id 屯蹦,這樣會有以下的情況:

如果 trx_id < 活躍的最小事務(wù)ID(up_limit_id),行記錄是在所有活躍的事務(wù)創(chuàng)建前就已經(jīng)提交了,那么這個行記錄對當(dāng)前事務(wù)是可見的绳姨。
如果trx_id > 活躍的最大事務(wù)ID(low_limit_id)登澜,行記錄是在所有活躍的事務(wù)之后才創(chuàng)建的,說明這個行記錄對當(dāng)前事務(wù)是不可見的飘庄。
如果 up_limit_id <= trx_id <=low_limit_id,說明該記錄需要在 trx_ids 集合中脑蠕,可能還處于活躍狀態(tài),因此我們需要在 trx_ids 集合中遍歷 跪削,如果trx_id 存在于 trx_ids 集合中谴仙,證明這個事務(wù) trx_id 還處于活躍狀態(tài),不可見碾盐,否則 晃跺,trx_id 不存在于 trx_ids 集合中,說明事務(wù)trx_id 已經(jīng)提交了毫玖,這行記錄是可見的掀虎。

  • 實際上活躍的最大的事務(wù)ID肯定是查詢生成的凌盯,因為生成這個活躍事務(wù)ID數(shù)組就是在查詢的時候生成的,查詢是不修改2列隱藏值的烹玉,所以trx_id永遠不可能等于活躍的最大事務(wù)ID(low_limit_id)
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末驰怎,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子二打,更是在濱河造成了極大的恐慌县忌,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,183評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件继效,死亡現(xiàn)場離奇詭異症杏,居然都是意外死亡,警方通過查閱死者的電腦和手機莲趣,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評論 3 399
  • 文/潘曉璐 我一進店門鸳慈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人喧伞,你說我怎么就攤上這事〖ɡ桑” “怎么了潘鲫?”我有些...
    開封第一講書人閱讀 168,766評論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長肋杖。 經(jīng)常有香客問我溉仑,道長,這世上最難降的妖魔是什么状植? 我笑而不...
    開封第一講書人閱讀 59,854評論 1 299
  • 正文 為了忘掉前任浊竟,我火速辦了婚禮,結(jié)果婚禮上津畸,老公的妹妹穿的比我還像新娘振定。我一直安慰自己,他們只是感情好肉拓,可當(dāng)我...
    茶點故事閱讀 68,871評論 6 398
  • 文/花漫 我一把揭開白布后频。 她就那樣靜靜地躺著,像睡著了一般暖途。 火紅的嫁衣襯著肌膚如雪卑惜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,457評論 1 311
  • 那天驻售,我揣著相機與錄音露久,去河邊找鬼。 笑死欺栗,一個胖子當(dāng)著我的面吹牛毫痕,可吹牛的內(nèi)容都是我干的壳快。 我是一名探鬼主播,決...
    沈念sama閱讀 40,999評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼镇草,長吁一口氣:“原來是場噩夢啊……” “哼眶痰!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起梯啤,我...
    開封第一講書人閱讀 39,914評論 0 277
  • 序言:老撾萬榮一對情侶失蹤竖伯,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后因宇,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體七婴,經(jīng)...
    沈念sama閱讀 46,465評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,543評論 3 342
  • 正文 我和宋清朗相戀三年察滑,在試婚紗的時候發(fā)現(xiàn)自己被綠了打厘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,675評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡贺辰,死狀恐怖户盯,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情饲化,我是刑警寧澤莽鸭,帶...
    沈念sama閱讀 36,354評論 5 351
  • 正文 年R本政府宣布,位于F島的核電站吃靠,受9級特大地震影響硫眨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜巢块,卻給世界環(huán)境...
    茶點故事閱讀 42,029評論 3 335
  • 文/蒙蒙 一礁阁、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧族奢,春花似錦姥闭、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,514評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至弥姻,卻和暖如春南片,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背庭敦。 一陣腳步聲響...
    開封第一講書人閱讀 33,616評論 1 274
  • 我被黑心中介騙來泰國打工疼进, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人秧廉。 一個月前我還...
    沈念sama閱讀 49,091評論 3 378
  • 正文 我出身青樓伞广,卻偏偏與公主長得像拣帽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子嚼锄,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,685評論 2 360

推薦閱讀更多精彩內(nèi)容