??
作為一個程序員闪彼,每日必打交道的就是數(shù)據(jù)庫甜孤,而現(xiàn)在市場對于MySQL數(shù)據(jù)庫的要求就是必會。(我自己觀察的啊,莫要認真……(#^.^#)? )缴川,那么今天我們就簡單聊一聊MySQL數(shù)據(jù)庫鎖茉稠。
一、什么是鎖
????????數(shù)據(jù)庫是一個多用戶使用的共享資源二跋。當(dāng)多個用戶并發(fā)地存取數(shù)據(jù)時战惊,在數(shù)據(jù)庫中就會產(chǎn)生多個事務(wù)同時存取同一數(shù)據(jù)的情況。若對并發(fā)操作不加控制就可能會讀取和存儲不正確的數(shù)據(jù)扎即,破壞數(shù)據(jù)庫的一致性吞获。
????加鎖是實現(xiàn)數(shù)據(jù)庫并發(fā)控制的一個非常重要的技術(shù)。
????當(dāng)事務(wù)在對某個數(shù)據(jù)對象進行操作前谚鄙,先向系統(tǒng)發(fā)出請求各拷,對其加鎖。加鎖后事務(wù)就對該數(shù)據(jù)對象有了一定的控制闷营,在該事務(wù)釋放鎖之前烤黍,其他的事務(wù)不能對此數(shù)據(jù)對象進行更新操作。
二傻盟、數(shù)據(jù)庫鎖分類
按照鎖的顆粒度 ?可分為:行級鎖速蕊、頁級鎖、表級鎖
按照鎖的級別 可分為:共享鎖娘赴、排它鎖
按照鎖的方式 可分為:自動鎖规哲、顯示鎖
按照鎖的使用方式 可分為:樂觀鎖、悲觀鎖
????
????簡單理解 :
共享鎖等價于讀鎖(Read Lock)
排它鎖等價于寫鎖(Write Lock)
????
悲觀鎖:指的是對數(shù)據(jù)被外界(包括本系統(tǒng)當(dāng)前的其他事務(wù)诽表,以及來自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度唉锌,因此,在整個數(shù)據(jù)處理過程中竿奏,將數(shù)據(jù)處于鎖定狀態(tài)袄简。
樂觀鎖: 采用了一種“樂觀”的方式,它只有在數(shù)據(jù) commit 時泛啸,才會進行排它性的檢查绿语。不過樂觀鎖也不是沒有缺點,樂觀鎖適用于寫操作比較少的情況平痰,即沖突很少發(fā)生的情況汞舱。如果經(jīng)常發(fā)生沖突的話,使用樂觀鎖反而會影響性能宗雇,降低系統(tǒng)的吞吐量昂芜。
????行級鎖、頁級鎖赔蒲、表級鎖
表級鎖:開銷小泌神,加鎖快良漱;不會出現(xiàn)死鎖;鎖定粒度大欢际,發(fā)生鎖沖突的概率最高母市,并發(fā)度最低。
行級鎖:開銷大损趋,加鎖慢患久;會出現(xiàn)死鎖;鎖定粒度最小浑槽,發(fā)生鎖沖突的概率最低蒋失,并發(fā)度也最高。
頁面鎖:開銷和加鎖時間界于表鎖和行鎖之間桐玻;會出現(xiàn)死鎖篙挽;鎖定粒度界于表鎖和行鎖之間,并發(fā)度一般镊靴。
三铣卡、MySQL 存儲引擎使用的鎖機制
MyISAM 存儲引擎采用的是表級鎖(table-level-locking),
InnoDB 存儲引擎既支持行級鎖(row-level-locking)也支持表級鎖偏竟,但是默認的情況下采用的是行級鎖煮落。
BDB 采用的是頁級鎖(page-level-locking),同時 BDB 也支持表級鎖 ? (我們不常使用到的一種存儲引擎踊谋,其他的不說了州邢,我也不知道 emo (?﹏?)!)
3.1 MyISAM 存儲引擎的鎖機制
????? ? ?當(dāng)我們對一張表進行查詢操作(select)時褪子,MyISAM 存儲引擎會對這張表自動加上一個讀鎖;
????????當(dāng)對這張表進行 插入骗村、修改嫌褪、刪除(insert、update胚股、delete)時笼痛,MyISAM 存儲引擎會對這張表自動加上一個寫鎖。
eg:
當(dāng)我們對一張表琅拌,進行查詢操作 s1缨伊,但還沒得到查詢結(jié)果時,這是新增一個查詢操作s2時进宝,s1和s2操作都不會被阻塞刻坊,s1和s2都可查出結(jié)果。由此能粗略的得出共享鎖對讀操作是兼容的党晋;
當(dāng)我們對一張表谭胚,進行查詢操作s1徐块,但還沒有得到查詢結(jié)果時,同時進行更新操作u1灾而,此時u1會被阻塞胡控,需要等待s1完成后,在進行u1旁趟。粗略的得出排它鎖對讀寫操作是不兼容的
上述說的都是自動鎖昼激,由MyISAM主動加鎖。手動鎖如下示例:
lock?tables?drug?read,prescription?read;select?sum(drug_pricel)?from?drug?;select?sum(prescription_pricel)?from?prescription?;unlock?tables;
鎖的顆粒度是在表上锡搜。
3.2橙困、 InnoDB 存儲引擎的鎖機制
InnoDB 存儲引擎支持事務(wù),并且在默認的情況下是自動提交事務(wù)的余爆,它的機制是為同一批事務(wù)提交之前加鎖纷宇,然后 commit 后再一起釋放。
關(guān)于事務(wù)自動提交蛾方,可通過設(shè)置autocommit =0關(guān)閉事務(wù)的自動提交像捶。
set?autocommit?=?0;
InnoDB 存儲引擎默認是 行級鎖 。
??eg:
??????當(dāng)我們對一張表 中的id=1的數(shù)據(jù)進行修改操作 u1時桩砰,在事務(wù)沒有commit時拓春,此時對id=2的數(shù)據(jù)也進行修改操作u2,此時可以發(fā)現(xiàn) u2是可以操作成功的亚隅,證明u2并沒有受到u1鎖的影響而發(fā)生阻塞硼莽;
????????但是如果我們對id=1的數(shù)據(jù)在進行修改操作u2,此時會發(fā)現(xiàn)u2 會被阻塞煮纵,需要等待u1執(zhí)行結(jié)束后在執(zhí)行u2懂鸵。
????????這便粗略的驗證了 InnoDB 默認加鎖的粒度是行級鎖
不過,有個前提條件行疏,那就是 :
查詢的字段上必須有索引匆光,如果沒有索引 InnoDB 還是會對整個表加鎖。
當(dāng)我們的 sql 語句操作字段沒有走索引時酿联,InnoDB 還是會在整個表這個粒度上加鎖终息。所以說,InnoDB 既支持行級鎖贞让,也支持表級鎖周崭。
四、死鎖
??????我們平時工作中使用的比較多的就是InnoDB 喳张,默認用的也是行級鎖续镇,
但是行級鎖一定比表級鎖好么?
????????其實不然蹲姐,行級鎖的并發(fā)度雖然比表級鎖要高磨取,但是表級鎖的開銷比較小人柿,加鎖的速度很快;行級鎖的開銷則比較大忙厌,并且加鎖的速度慢凫岖,最重要的是 ?
行級鎖可能會出現(xiàn)死鎖現(xiàn)象。
死鎖 ?:是指兩個或兩個以上的進程或線程在執(zhí)行過程中逢净,由于競爭資源或者由于彼此通信而造成的一種阻塞的現(xiàn)象哥放,若無外力作用,它們都將無法推進下去爹土。
形成死鎖必須滿足四個必要條件:
互斥條件
請求與保持條件
不剝奪條件
環(huán)路等待條件
互斥條件:是指進程對所分配到的資源進行排它性使用甥雕。說白了就是在一段時間內(nèi),某個資源每次只能被一個進程所占用胀茵。
請求與保持條件:是指進程已經(jīng)保持至少一個資源社露,但又提出了新的資源請求,而該資源已被其它進程占有琼娘,此時請求進程阻塞峭弟,但又對自己已獲得的其它資源保持不放,說人話就是“有了碗里的餅脱拼,還嚷嚷著要吃鍋里的湯”瞒瘸。
不剝奪條件:是指進程已獲得的資源在未使用完之前,不能被剝奪熄浓,只能由自己釋放情臭,說人話就是“自己拿到了就不給別人用,自己用完了才給別人”赌蔑。
環(huán)路等待條件:是指當(dāng)發(fā)生死鎖時俯在,必然存在著一個資源的請求環(huán)形鏈,若干進程在這個環(huán)形鏈中循環(huán)等待娃惯。
避免死鎖有以下幾種常見的策略:
設(shè)置獲得鎖的超時時間
避免長事務(wù)
避免事務(wù)中的用戶交互
降低隔離級別
好了朝巫,關(guān)于數(shù)據(jù)庫鎖就白話到這里吧。
…………………………………分割線……………………………
不積跬步石景,無以至千里;不積小流拙吉,無以成江海潮孽。
關(guān)注我,每天分享一些小知識點筷黔。分享自己的小心得往史,包含但不限于初、中佛舱、高級面試題呦W道0ぞ觥!
我都墨跡這么半天了 订歪,你不點關(guān)注脖祈,不點贊,不收藏刷晋,還不轉(zhuǎn)發(fā)盖高,你想干啥!Q凼S靼隆!