MySQL中的悲觀鎖與樂觀鎖
在關(guān)系型數(shù)據(jù)庫(kù)中,悲觀鎖與樂觀鎖是解決資源并發(fā)場(chǎng)景的解決方案,接下來將詳細(xì)講解🔎一下這兩個(gè)并發(fā)解決方案的實(shí)際使用及優(yōu)缺點(diǎn)。
首先定義一下數(shù)據(jù)庫(kù),做一個(gè)最簡(jiǎn)單的庫(kù)存表,如下設(shè)計(jì):
CREATE TABLE `order_stock` ( `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'ID', `oid` int(50) NOT NULL COMMENT '商品ID', `quantity` int(20) NOT NULL COMMENT '庫(kù)存', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
quantity代表著不同商品oid的庫(kù)存,接下來OCC及PCC使用此數(shù)據(jù)庫(kù)進(jìn)行演示。
樂觀鎖 OCC
它假設(shè)多用戶并發(fā)的事務(wù)在處理時(shí)不會(huì)彼此互相影響,各事務(wù)能夠在不產(chǎn)生鎖的情況下處理各自影響的那部分?jǐn)?shù)據(jù)。在提交數(shù)據(jù)更新之前,每個(gè)事務(wù)會(huì)先檢查在該事務(wù)讀取數(shù)據(jù)后,有沒有其他事務(wù)又修改了該數(shù)據(jù)。如果其他事務(wù)有更新的話,正在提交的事務(wù)會(huì)進(jìn)行回滾。
即“樂觀鎖🔒”認(rèn)為拿鎖的用戶多半是會(huì)成功的,因此在進(jìn)行完業(yè)務(wù)操作需要實(shí)際更新數(shù)據(jù)的最后一步再去拿一下鎖就好。這樣就可以避免使用數(shù)據(jù)庫(kù)自身定義的行鎖,可以避免死鎖現(xiàn)象的產(chǎn)生。
UPDATE order_stock SET quantity = quantity - 1 WHERE oid = 1 AND quantity - 1 > 0;
樂觀并發(fā)控制多數(shù)用于數(shù)據(jù)爭(zhēng)用不大、沖突較少的環(huán)境中,這種環(huán)境中,偶爾回滾事務(wù)的成本會(huì)低于讀取數(shù)據(jù)時(shí)鎖定數(shù)據(jù)的成本,因此可以獲得比其他并發(fā)控制方法更高的吞吐量。
悲觀鎖 PCC
它可以阻止一個(gè)事務(wù)以影響其他用戶的方式來修改數(shù)據(jù)。如果一個(gè)事務(wù)執(zhí)行的操作讀某行數(shù)據(jù)應(yīng)用了鎖,那只有當(dāng)這個(gè)事務(wù)把鎖釋放,其他事務(wù)才能夠執(zhí)行與該鎖沖突的操作。
這種設(shè)計(jì)采用了“一鎖🔒二查🔍三更新”模式,就是采用數(shù)據(jù)庫(kù)中自帶 select ... for update 關(guān)鍵字進(jìn)行對(duì)當(dāng)前事務(wù)添加行級(jí)鎖🔒,先將要操作的數(shù)據(jù)進(jìn)行鎖上,之后執(zhí)行對(duì)應(yīng)查詢數(shù)據(jù)并執(zhí)行更新操作。
BEGIN SELECT quantity FROM order_stock WHERE oid = 1 FOR UPDATE; UPDATE order_stock SET quantity = 2 WHERE oid = 1; COMMIT;
MySQL還有個(gè)問題是select ... for update語句執(zhí)行中所有掃描過的行都會(huì)被鎖上,這一點(diǎn)很容易造成問題。因此如果在MySQL中用悲觀鎖務(wù)必要確定走了索引,而不是全表掃描。
悲觀并發(fā)控制主要用于數(shù)據(jù)爭(zhēng)用激烈的環(huán)境,以及發(fā)生并發(fā)沖突時(shí)使用鎖保護(hù)數(shù)據(jù)的成本要低于回滾事務(wù)的成本的環(huán)境中。
OCC 和 PCC 優(yōu)缺點(diǎn)
OCC 優(yōu)點(diǎn)及缺點(diǎn)
【優(yōu)點(diǎn)】
- 樂觀鎖相信事務(wù)之間的數(shù)據(jù)競(jìng)爭(zhēng)(data race)的概率是比較小的,因此盡可能直接做下去,直到提交的時(shí)候才去鎖定,所以不會(huì)產(chǎn)生任何鎖和死鎖;
- 可以快速響應(yīng)事務(wù),隨著并發(fā)量增加,但會(huì)出現(xiàn)大量回滾出現(xiàn);
- 效率高,但是要控制好鎖的力度。
【缺點(diǎn)】
- 如果直接簡(jiǎn)單這么做,還是有可能會(huì)遇到不可預(yù)期的結(jié)果,例如兩個(gè)事務(wù)都讀取了數(shù)據(jù)庫(kù)的某一行,經(jīng)過修改以后寫回?cái)?shù)據(jù)庫(kù),這時(shí)就遇到了問題;
- 隨著并發(fā)量增加,但會(huì)出現(xiàn)大量回滾出現(xiàn)。
PCC 優(yōu)點(diǎn)及缺點(diǎn)
【優(yōu)點(diǎn)】
“先取鎖再訪問”的保守策略,為數(shù)據(jù)處理的安全提供了保證;
【缺點(diǎn)】
- 依賴數(shù)據(jù)庫(kù)鎖,效率低;
- 處理加鎖的機(jī)制會(huì)讓數(shù)據(jù)庫(kù)產(chǎn)生額外的開銷,還有增加產(chǎn)生死鎖的機(jī)會(huì);
- 降低了并行性,一個(gè)事務(wù)如果鎖定了某行數(shù)據(jù),其他事務(wù)就必須等待該事務(wù)處理完才可以處理那行數(shù)據(jù)。
以上就是MySQL中的悲觀鎖與樂觀鎖的詳細(xì)內(nèi)容,更多關(guān)于MySQL 悲觀鎖與樂觀鎖的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
MySQL中having和where的區(qū)別及應(yīng)用詳解
這篇文章主要給大家詳細(xì)介紹了MySQL中having和where的區(qū)別以及他們的使用方法,文中有相關(guān)的代碼示例,具有一定的參考價(jià)值,需要的朋友可以參考下2023-06-06
mysql 5.6 從陌生到熟練之_數(shù)據(jù)庫(kù)備份恢復(fù)的實(shí)現(xiàn)方法
下面小編就為大家?guī)硪黄猰ysql 5.6 從陌生到熟練之_數(shù)據(jù)庫(kù)備份恢復(fù)的實(shí)現(xiàn)方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-10-10
MySQL binlog_ignore_db 參數(shù)的具體使用
這篇文章主要介紹了MySQL binlog_ignore_db 參數(shù)的具體作用,幫助大家更好的理解和使用MySQL數(shù)據(jù)庫(kù),感興趣的朋友可以了解下2020-12-12
Mysql 查詢數(shù)據(jù)庫(kù)容量大小的方法步驟
這篇文章主要介紹了Mysql 查詢數(shù)據(jù)庫(kù)容量大小的方法步驟,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06
Linux中部署MySQL環(huán)境的四種方式圖文詳解
這篇文章主要介紹了Linux中部署MySQL環(huán)境的四種方式,本文通過圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧2023-11-11
windows下mysql?8.0.27?安裝配置方法圖文教程
這篇文章主要為大家詳細(xì)介紹了windows下mysql?8.0.27?安裝配置方法圖文教程,文中安裝步驟介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-04-04

