??
作為一個(gè)程序員,每日必打交道的就是數(shù)據(jù)庫(kù),而現(xiàn)在市場(chǎng)對(duì)于MySQL數(shù)據(jù)庫(kù)的要求就是必會(huì)。(我自己觀察的啊,莫要認(rèn)真……(#^.^#)? ),那么今天我們就簡(jiǎn)單聊一聊MySQL數(shù)據(jù)庫(kù)鎖。
一、什么是鎖
????????數(shù)據(jù)庫(kù)是一個(gè)多用戶使用的共享資源。當(dāng)多個(gè)用戶并發(fā)地存取數(shù)據(jù)時(shí),在數(shù)據(jù)庫(kù)中就會(huì)產(chǎn)生多個(gè)事務(wù)同時(shí)存取同一數(shù)據(jù)的情況。若對(duì)并發(fā)操作不加控制就可能會(huì)讀取和存儲(chǔ)不正確的數(shù)據(jù),破壞數(shù)據(jù)庫(kù)的一致性。
????加鎖是實(shí)現(xiàn)數(shù)據(jù)庫(kù)并發(fā)控制的一個(gè)非常重要的技術(shù)。
????當(dāng)事務(wù)在對(duì)某個(gè)數(shù)據(jù)對(duì)象進(jìn)行操作前,先向系統(tǒng)發(fā)出請(qǐng)求,對(duì)其加鎖。加鎖后事務(wù)就對(duì)該數(shù)據(jù)對(duì)象有了一定的控制,在該事務(wù)釋放鎖之前,其他的事務(wù)不能對(duì)此數(shù)據(jù)對(duì)象進(jìn)行更新操作。
二、數(shù)據(jù)庫(kù)鎖分類
按照鎖的顆粒度 ?可分為:行級(jí)鎖、頁(yè)級(jí)鎖、表級(jí)鎖
按照鎖的級(jí)別 可分為:共享鎖、排它鎖
按照鎖的方式 可分為:自動(dòng)鎖、顯示鎖
按照鎖的使用方式 可分為:樂觀鎖、悲觀鎖
????
????簡(jiǎn)單理解 :
共享鎖等價(jià)于讀鎖(Read Lock)
排它鎖等價(jià)于寫鎖(Write Lock)
????
悲觀鎖:指的是對(duì)數(shù)據(jù)被外界(包括本系統(tǒng)當(dāng)前的其他事務(wù),以及來自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度,因此,在整個(gè)數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。
樂觀鎖: 采用了一種“樂觀”的方式,它只有在數(shù)據(jù) commit 時(shí),才會(huì)進(jìn)行排它性的檢查。不過樂觀鎖也不是沒有缺點(diǎn),樂觀鎖適用于寫操作比較少的情況,即沖突很少發(fā)生的情況。如果經(jīng)常發(fā)生沖突的話,使用樂觀鎖反而會(huì)影響性能,降低系統(tǒng)的吞吐量。
????行級(jí)鎖、頁(yè)級(jí)鎖、表級(jí)鎖
表級(jí)鎖:開銷小,加鎖快;不會(huì)出現(xiàn)死鎖;鎖定粒度大,發(fā)生鎖沖突的概率最高,并發(fā)度最低。
行級(jí)鎖:開銷大,加鎖慢;會(huì)出現(xiàn)死鎖;鎖定粒度最小,發(fā)生鎖沖突的概率最低,并發(fā)度也最高。
頁(yè)面鎖:開銷和加鎖時(shí)間界于表鎖和行鎖之間;會(huì)出現(xiàn)死鎖;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般。
三、MySQL 存儲(chǔ)引擎使用的鎖機(jī)制
MyISAM 存儲(chǔ)引擎采用的是表級(jí)鎖(table-level-locking),
InnoDB 存儲(chǔ)引擎既支持行級(jí)鎖(row-level-locking)也支持表級(jí)鎖,但是默認(rèn)的情況下采用的是行級(jí)鎖。
BDB 采用的是頁(yè)級(jí)鎖(page-level-locking),同時(shí) BDB 也支持表級(jí)鎖 ? (我們不常使用到的一種存儲(chǔ)引擎,其他的不說了,我也不知道 emo (?﹏?)!)
3.1 MyISAM 存儲(chǔ)引擎的鎖機(jī)制
????? ? ?當(dāng)我們對(duì)一張表進(jìn)行查詢操作(select)時(shí),MyISAM 存儲(chǔ)引擎會(huì)對(duì)這張表自動(dòng)加上一個(gè)讀鎖;
????????當(dāng)對(duì)這張表進(jìn)行 插入、修改、刪除(insert、update、delete)時(shí),MyISAM 存儲(chǔ)引擎會(huì)對(duì)這張表自動(dòng)加上一個(gè)寫鎖。
eg:
當(dāng)我們對(duì)一張表,進(jìn)行查詢操作 s1,但還沒得到查詢結(jié)果時(shí),這是新增一個(gè)查詢操作s2時(shí),s1和s2操作都不會(huì)被阻塞,s1和s2都可查出結(jié)果。由此能粗略的得出共享鎖對(duì)讀操作是兼容的;
當(dāng)我們對(duì)一張表,進(jìn)行查詢操作s1,但還沒有得到查詢結(jié)果時(shí),同時(shí)進(jìn)行更新操作u1,此時(shí)u1會(huì)被阻塞,需要等待s1完成后,在進(jìn)行u1。粗略的得出排它鎖對(duì)讀寫操作是不兼容的
上述說的都是自動(dòng)鎖,由MyISAM主動(dòng)加鎖。手動(dòng)鎖如下示例:
lock?tables?drug?read,prescription?read;select?sum(drug_pricel)?from?drug?;select?sum(prescription_pricel)?from?prescription?;unlock?tables;
鎖的顆粒度是在表上。
3.2、 InnoDB 存儲(chǔ)引擎的鎖機(jī)制
InnoDB 存儲(chǔ)引擎支持事務(wù),并且在默認(rèn)的情況下是自動(dòng)提交事務(wù)的,它的機(jī)制是為同一批事務(wù)提交之前加鎖,然后 commit 后再一起釋放。
關(guān)于事務(wù)自動(dòng)提交,可通過設(shè)置autocommit =0關(guān)閉事務(wù)的自動(dòng)提交。
set?autocommit?=?0;
InnoDB 存儲(chǔ)引擎默認(rèn)是 行級(jí)鎖 。
??eg:
??????當(dāng)我們對(duì)一張表 中的id=1的數(shù)據(jù)進(jìn)行修改操作 u1時(shí),在事務(wù)沒有commit時(shí),此時(shí)對(duì)id=2的數(shù)據(jù)也進(jìn)行修改操作u2,此時(shí)可以發(fā)現(xiàn) u2是可以操作成功的,證明u2并沒有受到u1鎖的影響而發(fā)生阻塞;
????????但是如果我們對(duì)id=1的數(shù)據(jù)在進(jìn)行修改操作u2,此時(shí)會(huì)發(fā)現(xiàn)u2 會(huì)被阻塞,需要等待u1執(zhí)行結(jié)束后在執(zhí)行u2。
????????這便粗略的驗(yàn)證了 InnoDB 默認(rèn)加鎖的粒度是行級(jí)鎖
不過,有個(gè)前提條件,那就是 :
查詢的字段上必須有索引,如果沒有索引 InnoDB 還是會(huì)對(duì)整個(gè)表加鎖。
當(dāng)我們的 sql 語(yǔ)句操作字段沒有走索引時(shí),InnoDB 還是會(huì)在整個(gè)表這個(gè)粒度上加鎖。所以說,InnoDB 既支持行級(jí)鎖,也支持表級(jí)鎖。
四、死鎖
??????我們平時(shí)工作中使用的比較多的就是InnoDB ,默認(rèn)用的也是行級(jí)鎖,
但是行級(jí)鎖一定比表級(jí)鎖好么?
????????其實(shí)不然,行級(jí)鎖的并發(fā)度雖然比表級(jí)鎖要高,但是表級(jí)鎖的開銷比較小,加鎖的速度很快;行級(jí)鎖的開銷則比較大,并且加鎖的速度慢,最重要的是 ?
行級(jí)鎖可能會(huì)出現(xiàn)死鎖現(xiàn)象。
死鎖 ?:是指兩個(gè)或兩個(gè)以上的進(jìn)程或線程在執(zhí)行過程中,由于競(jìng)爭(zhēng)資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象,若無(wú)外力作用,它們都將無(wú)法推進(jìn)下去。
形成死鎖必須滿足四個(gè)必要條件:
互斥條件
請(qǐng)求與保持條件
不剝奪條件
環(huán)路等待條件
互斥條件:是指進(jìn)程對(duì)所分配到的資源進(jìn)行排它性使用。說白了就是在一段時(shí)間內(nèi),某個(gè)資源每次只能被一個(gè)進(jìn)程所占用。
請(qǐng)求與保持條件:是指進(jìn)程已經(jīng)保持至少一個(gè)資源,但又提出了新的資源請(qǐng)求,而該資源已被其它進(jìn)程占有,此時(shí)請(qǐng)求進(jìn)程阻塞,但又對(duì)自己已獲得的其它資源保持不放,說人話就是“有了碗里的餅,還嚷嚷著要吃鍋里的湯”。
不剝奪條件:是指進(jìn)程已獲得的資源在未使用完之前,不能被剝奪,只能由自己釋放,說人話就是“自己拿到了就不給別人用,自己用完了才給別人”。
環(huán)路等待條件:是指當(dāng)發(fā)生死鎖時(shí),必然存在著一個(gè)資源的請(qǐng)求環(huán)形鏈,若干進(jìn)程在這個(gè)環(huán)形鏈中循環(huán)等待。
避免死鎖有以下幾種常見的策略:
設(shè)置獲得鎖的超時(shí)時(shí)間
避免長(zhǎng)事務(wù)
避免事務(wù)中的用戶交互
降低隔離級(jí)別
好了,關(guān)于數(shù)據(jù)庫(kù)鎖就白話到這里吧。
…………………………………分割線……………………………
不積跬步,無(wú)以至千里;不積小流,無(wú)以成江海。
關(guān)注我,每天分享一些小知識(shí)點(diǎn)。分享自己的小心得,包含但不限于初、中、高級(jí)面試題呦!!!
我都墨跡這么半天了 ,你不點(diǎn)關(guān)注,不點(diǎn)贊,不收藏,還不轉(zhuǎn)發(fā),你想干啥!!!!