GoFrame 鏈?zhǔn)讲僮?悲觀(guān)鎖&樂(lè)觀(guān)鎖

2022-04-02 11:45 更新

悲觀(guān)鎖(?Pessimistic Lock?),顧名思義,就是很悲觀(guān),每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人會(huì)修改,所以每次在拿數(shù)據(jù)的時(shí)候都會(huì)上鎖,這樣別人想拿這個(gè)數(shù)據(jù)就會(huì)阻塞直到它拿到鎖。傳統(tǒng)的關(guān)系型數(shù)據(jù)庫(kù)里邊就用到了很多這種鎖機(jī)制,比如行鎖、表鎖、讀鎖、寫(xiě)鎖等,都是在做操作之前先上鎖。

樂(lè)觀(guān)鎖(?Optimistic Lock?),顧名思義,就是很樂(lè)觀(guān),每次去拿數(shù)據(jù)的時(shí)候都認(rèn)為別人不會(huì)修改,所以不會(huì)上鎖,但是在更新的時(shí)候會(huì)判斷一下在此期間別人有沒(méi)有去更新這個(gè)數(shù)據(jù),可以使用版本號(hào)等機(jī)制實(shí)現(xiàn)。樂(lè)觀(guān)鎖適用于多讀的應(yīng)用類(lèi)型,這樣可以提高吞吐量。

悲觀(guān)鎖使用

相關(guān)方法

func (m *Model) LockUpdate() *Model
func (m *Model) LockShared() *Model

?gdb?模塊的鏈?zhǔn)讲僮魈峁┝藘蓚€(gè)方法幫助您在?SQL?語(yǔ)句中實(shí)現(xiàn)“悲觀(guān)鎖”??梢栽诓樵?xún)中使用?LockShared?方法從而在運(yùn)行語(yǔ)句時(shí)帶一把”共享鎖“。共享鎖可以避免被選擇的行被修改直到事務(wù)提交:

db.Model("users").Ctx(ctx).Where("votes>?", 100).LockShared().All();

上面這個(gè)查詢(xún)等價(jià)于下面這條SQL語(yǔ)句:

SELECT * FROM `users` WHERE `votes` > 100 LOCK IN SHARE MODE

此外你還可以使用?LockUpdate?方法。該方法用于創(chuàng)建?FOR UPDATE?鎖,避免選擇行被其它共享鎖修改或刪除:

db.Model("users").Ctx(ctx).Where("votes>?", 100).LockUpdate().All();

上面這個(gè)查詢(xún)等價(jià)于下面這條SQL語(yǔ)句:

SELECT * FROM `users` WHERE `votes` > 100 FOR UPDATE

?FOR UPDATE? 與 ?LOCK IN SHARE MODE? 都是用于確保被選中的記錄值不能被其它事務(wù)更新(上鎖),兩者的區(qū)別在于 ?LOCK IN SHARE MODE? 不會(huì)阻塞其它事務(wù)讀取被鎖定行記錄的值,而 ?FOR UPDATE?會(huì)阻塞其他鎖定性讀對(duì)鎖定行的讀取(非鎖定性讀仍然可以讀取這些記錄,?LOCK IN SHARE MODE? 和 ?FOR UPDATE?都是鎖定性讀)。

這么說(shuō)比較抽象,我們舉個(gè)計(jì)數(shù)器的例子:在一條語(yǔ)句中讀取一個(gè)值,然后在另一條語(yǔ)句中更新這個(gè)值。使用 ?LOCK IN SHARE MODE? 的話(huà)可以允許兩個(gè)事務(wù)讀取相同的初始化值,所以執(zhí)行兩個(gè)事務(wù)之后最終計(jì)數(shù)器的值+1;而如果使用 ?FOR UPDATE?的話(huà),會(huì)鎖定第二個(gè)事務(wù)對(duì)記錄值的讀取直到第一個(gè)事務(wù)執(zhí)行完成,這樣計(jì)數(shù)器的最終結(jié)果就是+2了。

樂(lè)觀(guān)鎖使用

樂(lè)觀(guān)鎖,大多是基于數(shù)據(jù)版本 (Version)記錄機(jī)制實(shí)現(xiàn)。何謂數(shù)據(jù)版本?即為數(shù)據(jù)增加一個(gè)版本標(biāo)識(shí),在基于數(shù)據(jù)庫(kù)表的版本解決方案中,一般是通過(guò)為數(shù)據(jù)庫(kù)表增加一個(gè)?version?字段來(lái)實(shí)現(xiàn)。

讀取出數(shù)據(jù)時(shí),將此版本號(hào)一同讀出,之后更新時(shí),對(duì)此版本號(hào)加一。此時(shí),將提交數(shù)據(jù)的版本數(shù)據(jù)與數(shù)據(jù)庫(kù)表對(duì)應(yīng)記錄的當(dāng)前版本信息進(jìn)行比對(duì),如果提交的數(shù)據(jù)版本號(hào)大于數(shù)據(jù)庫(kù)表當(dāng)前版本號(hào),則予以更新,否則認(rèn)為是過(guò)期數(shù)據(jù)。

鎖機(jī)制總結(jié)

兩種鎖各有優(yōu)缺點(diǎn),不可認(rèn)為一種好于另一種,像樂(lè)觀(guān)鎖適用于寫(xiě)比較少的情況下,即沖突真的很少發(fā)生的時(shí)候,這樣可以省去了鎖的開(kāi)銷(xiāo),加大了系統(tǒng)的整個(gè)吞吐量。但如果經(jīng)常產(chǎn)生沖突,上層應(yīng)用會(huì)不斷的進(jìn)行重試,這樣反倒是降低了性能,所以這種情況下用悲觀(guān)鎖就比較合適。


以上內(nèi)容是否對(duì)您有幫助:
在線(xiàn)筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)