MySQL的鎖

數(shù)據(jù)庫(kù)鎖

概述

相對(duì)其他數(shù)據(jù)庫(kù)而言,MySQL的鎖機(jī)制比較簡(jiǎn)單贫母,其最顯著的特點(diǎn)是不同的存儲(chǔ)引擎支持不同的鎖機(jī)制。比如彩扔,MyISAM和MEMORY存儲(chǔ)引擎采用的是表級(jí)鎖(table-level locking);InnoDB存儲(chǔ)引擎既支持行級(jí)鎖( row-level locking)蕉拢,也支持表級(jí)鎖场斑,但默認(rèn)情況下是采用行級(jí)鎖话浇。

MySQL主要的兩種鎖的特性可大致歸納如下:

  • 表級(jí)鎖: 開(kāi)銷小扩灯,加鎖快媚赖;不會(huì)出現(xiàn)死鎖(因?yàn)镸yISAM會(huì)一次性獲得SQL所需的全部鎖)霜瘪;鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)度最低惧磺。
  • 行級(jí)鎖: 開(kāi)銷大颖对,加鎖慢;會(huì)出現(xiàn)死鎖磨隘;鎖定粒度最小惜互,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。

考慮上述特點(diǎn)琳拭,表級(jí)鎖使用與并發(fā)性不高,以查詢?yōu)橹髅柩椋倭扛碌膽?yīng)用白嘁,比如小型的web應(yīng)用;而行級(jí)鎖適用于高并發(fā)環(huán)境下膘流,對(duì)事務(wù)完整性要求較高的系統(tǒng)絮缅,如在線事務(wù)處理系統(tǒng)。

MyISAM鎖細(xì)述

(1). 鎖模式

MySQL的表級(jí)鎖有兩種模式: 表共享讀鎖(Table Read Lock)和表獨(dú)占寫鎖(Table Write Lock)呼股。

(2). 如何加鎖

當(dāng)MyISAM在執(zhí)行查詢語(yǔ)句時(shí)耕魄,會(huì)自動(dòng)給涉及到表加讀鎖,在執(zhí)行更新操作時(shí)彭谁,會(huì)加寫鎖吸奴。當(dāng)然用戶也可以用LOCK TABLE 去顯式的加鎖。顯式的加鎖一般是應(yīng)用于:需要在一個(gè)時(shí)間點(diǎn)實(shí)現(xiàn)多個(gè)表的一致性讀取缠局,不然的話则奥,可能讀第一個(gè)表時(shí),其他表由于還沒(méi)進(jìn)行讀操作狭园,沒(méi)有自動(dòng)加鎖读处,可能數(shù)據(jù)會(huì)發(fā)生改變。并且顯示加鎖后只能訪問(wèn)加鎖的表唱矛,不能訪問(wèn)其他表罚舱。

(3). 并發(fā)插入

MyISAM存儲(chǔ)引擎有個(gè)系統(tǒng)變量 concurrent_insert,專門用來(lái)控制并發(fā)插入的行為绎谦,可以取 0 管闷, 1 , 2燥滑。

0表示不允許并發(fā)插入渐北,1表示表中間沒(méi)有刪除的行時(shí)可以在表末尾插入,2表示總是可以插入铭拧。

一般如果對(duì)并發(fā)要求比較高的情況下赃蛛,可以設(shè)置為2恃锉,總是可以插入,然后定期在數(shù)據(jù)庫(kù)空閑時(shí)間對(duì)表進(jìn)行optimize呕臂。

(4). 鎖的調(diào)度

需要注意的是破托,其中讀操作不會(huì)阻塞其他用戶對(duì)同一表的讀請(qǐng)求,但會(huì)阻塞對(duì)同一表的寫請(qǐng)求歧蒋;并且當(dāng)寫鎖和讀鎖同時(shí)被申請(qǐng)時(shí)土砂,優(yōu)先獲得寫鎖,這也這正是表級(jí)鎖發(fā)生鎖沖突概率最高的原因谜洽,因?yàn)閷戞i可能會(huì)一直阻塞讀鎖萝映,所以不適合有大量寫操作的環(huán)境下工作。這一問(wèn)題可以通過(guò)設(shè)置low-priority-updates這一啟動(dòng)參數(shù)來(lái)降低寫的優(yōu)先級(jí)阐虚。
雖然寫鎖優(yōu)先于讀鎖獲取序臂,但是長(zhǎng)時(shí)間的查詢操作也可能會(huì)讓寫操作餓死,所以盡量避免一條SQL語(yǔ)句執(zhí)行所有的查詢实束,應(yīng)該進(jìn)行必要的分解奥秆。

InnoDB鎖細(xì)述

由于InnoDB支持事務(wù),并默認(rèn)是使用行級(jí)鎖咸灿,所以InnoDB的鎖問(wèn)題和MyISAM鎖問(wèn)題還是有蠻大差別的构订。

(1). 鎖模式

共享鎖(S)和排他鎖(X),分別類似于MyISAM的讀鎖和寫鎖避矢。對(duì)于 UPDATE悼瘾、 DELETE 和 INSERT 語(yǔ)句,InnoDB會(huì)自動(dòng)給涉及數(shù)據(jù)集加排他鎖(X)谷异;對(duì)于普通 SELECT 語(yǔ)句分尸,InnoDB不會(huì)加任何鎖。

(2). 如何加鎖

可以顯式的加鎖歹嘹,用lock in share mode 顯式的加共享鎖箩绍,用 for update 顯式的加排他鎖。

需要注意的是尺上,如果線程A加了共享鎖后材蛛,線程B對(duì)同一個(gè)表加了共享鎖,那么兩個(gè)線程需要進(jìn)行更新操作時(shí)會(huì)產(chǎn)生死鎖怎抛。所以卑吭,進(jìn)行更新操作時(shí)最好加排他鎖。

(3). InnoDB行鎖的實(shí)現(xiàn)方式——索引加鎖

這一點(diǎn)與Oracle不同马绝,所以這也意味著(重要):1. 只有通過(guò)索引條件檢索數(shù)據(jù)時(shí)豆赏,InnoDB才會(huì)使用行級(jí)鎖,否則會(huì)使用表級(jí)鎖。 2. 即使是訪問(wèn)不同行的記錄掷邦,如果使用的是相同的索引鍵白胀,會(huì)發(fā)生鎖沖突。 3. 如果數(shù)據(jù)表建有多個(gè)索引時(shí)抚岗,可以通過(guò)不同的索引鎖定不同的行或杠。

(4). 間隙鎖

InnoDB支持事務(wù),為了滿足隔離級(jí)別的要求宣蔚,InnoDB有個(gè)間隙鎖向抢,當(dāng)使用范圍查找時(shí),InnoDB會(huì)給滿足key范圍要求胚委,但實(shí)際并不存在的記錄加鎖挟鸠。例如:select * from user where id > 100 for updata 會(huì)給ID>100的記錄加排他鎖,滿足這個(gè)范圍亩冬,但不存在的記錄兄猩,會(huì)加間隙鎖,這樣可以避免幻讀鉴未,避免讀取的時(shí)候插入滿足條件的記錄。

(5). 隔離級(jí)別與鎖

一般來(lái)說(shuō)鸠姨,隔離級(jí)別越高铜秆,加鎖就越嚴(yán)格。這樣讶迁,產(chǎn)生鎖沖突的概率就越大连茧,一般實(shí)際應(yīng)用中,通過(guò)優(yōu)化應(yīng)用邏輯巍糯,選用 可提交讀 級(jí)別就夠了啸驯。對(duì)于一些確實(shí)需要更高隔離級(jí)別的事務(wù),再通過(guò)set session transaction isolation level+"級(jí)別" 來(lái)動(dòng)態(tài)改變滿足需求祟峦。

死鎖

MyISAM是沒(méi)有死鎖問(wèn)題的罚斗,因?yàn)樗麜?huì)一次性獲得所有的鎖。InnoDB發(fā)生死鎖后一般能自動(dòng)檢測(cè)到宅楞,并使一個(gè)事務(wù)釋放鎖并回退针姿,另一個(gè)事務(wù)獲得鎖,繼續(xù)完成事務(wù)厌衙。

在應(yīng)用中距淫,可以通過(guò)如下方式來(lái)盡可能的避免死鎖:

(1) 如果不同的程序會(huì)并發(fā)的存取多個(gè)表,應(yīng)盡量約定以相同的順序來(lái)訪問(wèn)表婶希,這樣可以大大降低產(chǎn)生死鎖的機(jī)會(huì)榕暇。

(2) 在程序以批量方式處理數(shù)據(jù)時(shí),如果事先對(duì)數(shù)據(jù)排序,保證每個(gè)線程按固定的順序來(lái)處理記錄彤枢,也可以大大的降低出現(xiàn)死鎖的可能狰晚。

案例

秒殺一

## 查詢庫(kù)存,由于是主鍵查詢使用到了索引堂污,所以是行級(jí)鎖
SELECT number FROM seckill WHERE seckill_id=? FOR UPDATE
## 如果庫(kù)存大于秒殺數(shù)則更新家肯,UPDATE 操作也是行級(jí)鎖
UPDATE seckill  SET number=number-1 WHERE seckill_id=?

秒殺二

//直接更新數(shù)據(jù),如果count為1秒殺成功否則失敗
UPDATE seckill  SET number=number-1 WHERE seckill_id=? AND number>0

秒殺三

//獲取商品版本號(hào)以及剩余數(shù)量
SELECT version,number  FROM seckill WHERE seckill_id=?
//判斷剩余數(shù)量是否充足并更新
UPDATE seckill  SET number=number-?,version=version+1 WHERE seckill_id=? AND version = ? 
//如果更新數(shù)量等于1秒殺成功否則失敗

Mysql innodb雖是鎖行的盟猖,但是如果沒(méi)有索引讨衣,或者索引唯一性不是特別強(qiáng),那就要鎖表了式镐。

加鎖對(duì)并發(fā)訪問(wèn)的影響體現(xiàn)在鎖的粒度上反镇,可見(jiàn)行鎖粒度最小,并發(fā)訪問(wèn)最好娘汞,頁(yè)鎖粒度最大歹茶,表鎖介于2者之間。

鎖有兩種:悲觀鎖和樂(lè)觀鎖你弦。悲觀鎖假定其他用戶企圖訪問(wèn)或者改變你正在訪問(wèn)惊豺、更改的對(duì)象的概率是很高的,因此在悲觀鎖的環(huán)境中禽作,在你開(kāi)始改變此對(duì)象之前就將該對(duì)象鎖住尸昧,并且直到你提交了所作的更改之后才釋放鎖。悲觀的缺陷是不論是頁(yè)鎖還是行鎖旷偿,加鎖的時(shí)間可能會(huì)很長(zhǎng)烹俗,這樣可能會(huì)長(zhǎng)時(shí)間的限制其他用戶的訪問(wèn),也就是說(shuō)悲觀鎖的并發(fā)訪問(wèn)性不好萍程。

與悲觀鎖相反幢妄,樂(lè)觀鎖則認(rèn)為其他用戶企圖改變你正在更改的對(duì)象的概率是很小的,因此樂(lè)觀鎖直到你準(zhǔn)備提交所作的更改時(shí)才將對(duì)象鎖住茫负,當(dāng)你讀取以及改變?cè)搶?duì)象時(shí)并不加鎖蕉鸳。可見(jiàn)樂(lè)觀鎖加鎖的時(shí)間要比悲觀鎖短忍法,樂(lè)觀鎖可以用較大的鎖粒度獲得較好的并發(fā)訪問(wèn)性能置吓。但是如果第二個(gè)用戶恰好在第一個(gè)用戶提交更改之前讀取了該對(duì)象,那么當(dāng)他完成了自己的更改進(jìn)行提交時(shí)缔赠,數(shù)據(jù)庫(kù)就會(huì)發(fā)現(xiàn)該對(duì)象已經(jīng)變化了衍锚,這樣,第二個(gè)用戶不得不重新讀取該對(duì)象并作出更改嗤堰。這說(shuō)明在樂(lè)觀鎖環(huán)境中戴质,會(huì)增加并發(fā)用戶讀取對(duì)象的次數(shù)度宦。

參考

https://www.cnblogs.com/zhanht/p/5431273.html

https://www.cnblogs.com/liujiacai/p/7605612.html

https://www.cnblogs.com/claireyuancy/p/7258314.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市告匠,隨后出現(xiàn)的幾起案子戈抄,更是在濱河造成了極大的恐慌,老刑警劉巖后专,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件划鸽,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡戚哎,警方通過(guò)查閱死者的電腦和手機(jī)裸诽,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)型凳,“玉大人丈冬,你說(shuō)我怎么就攤上這事「食” “怎么了埂蕊?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)疏唾。 經(jīng)常有香客問(wèn)我蓄氧,道長(zhǎng),這世上最難降的妖魔是什么槐脏? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任匀们,我火速辦了婚禮,結(jié)果婚禮上准给,老公的妹妹穿的比我還像新娘。我一直安慰自己重抖,他們只是感情好露氮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著钟沛,像睡著了一般畔规。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上恨统,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天叁扫,我揣著相機(jī)與錄音,去河邊找鬼畜埋。 笑死莫绣,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的悠鞍。 我是一名探鬼主播对室,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了掩宜?” 一聲冷哼從身側(cè)響起蔫骂,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎牺汤,沒(méi)想到半個(gè)月后辽旋,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡檐迟,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年补胚,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片锅减。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡糖儡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出怔匣,到底是詐尸還是另有隱情握联,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布每瞒,位于F島的核電站金闽,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏剿骨。R本人自食惡果不足惜代芜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望浓利。 院中可真熱鬧挤庇,春花似錦、人聲如沸贷掖。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)苹威。三九已至昆咽,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間牙甫,已是汗流浹背掷酗。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留窟哺,地道東北人泻轰。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像且轨,于是被迫代替她去往敵國(guó)和親糕殉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子亩鬼,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

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

  • 當(dāng)一個(gè)系統(tǒng)訪問(wèn)量上來(lái)的時(shí)候,不只是數(shù)據(jù)庫(kù)性能瓶頸問(wèn)題了阿蝶,數(shù)據(jù)庫(kù)數(shù)據(jù)安全也會(huì)浮現(xiàn)雳锋,這時(shí)候合理使用數(shù)據(jù)庫(kù)鎖機(jī)制就顯得異...
    初來(lái)的雨天閱讀 3,571評(píng)論 0 22
  • 目錄:1.鎖的定義與分類(表、行羡洁、頁(yè))2.鎖相關(guān)的語(yǔ)句(查看鎖)3.mysql事務(wù)4.樂(lè)觀鎖和悲觀鎖5.數(shù)據(jù)庫(kù)死鎖...
    lbcBoy閱讀 3,721評(píng)論 1 6
  • 對(duì)于DB來(lái)說(shuō),經(jīng)常會(huì)面對(duì)并發(fā)問(wèn)題玷过,但是開(kāi)發(fā)的時(shí)候DB總是能很好的解決并發(fā)的問(wèn)題。那么面對(duì)并發(fā)DB是怎么進(jìn)行控制的呢...
    一只小哈閱讀 2,418評(píng)論 2 34
  • 文章導(dǎo)讀: 累兮筑煮,累兮辛蚊,要死兮...... 本文解決問(wèn)題: 1、表級(jí)鎖定(讀鎖真仲、寫鎖) 2袋马、行級(jí)鎖定(共享鎖、排他...
    創(chuàng)造new_world閱讀 640評(píng)論 0 1
  • 【今日晨讀】 【今日話題】 【今日讀書(shū)】 【今日運(yùn)動(dòng)】5k
    射手先森閱讀 159評(píng)論 0 0