悲觀鎖與樂觀鎖

2021-05-28 00:24:30 字數 2156 閱讀 6524

悲觀鎖與樂觀鎖

----------

悲觀鎖【pessimistic locking】

顧名思義就是採用一種悲觀的態度來對待事務併發問題,我們認為系統中的併發更新會非常頻繁,並且事務失敗 了以後重來的開銷很大,這樣以來,我們就需要採用真正意義上的鎖來進行實現。

悲觀鎖的基本思想就是每次一 個事務讀取某一條記錄後,就會把這條記錄鎖住,這樣其它的事務要想更新,必須等以前的事務提交或者回滾解 除鎖。

假如我們資料庫事務的隔離級別設定為讀取已提交或者更低,那麼通過悲觀鎖,我們控制了不可重複讀的問題, 但是不能避免幻影讀的問題,因為要想避免我們就需要設定資料庫隔離級別為serializable,而一般情況下我們都 會採取讀取已提交或者更低隔離級別,並配合樂觀或者悲觀鎖來實現併發控制,所以幻影讀問題是不能避免的,如 果想避免幻影讀問題,那麼你只能依靠資料庫的serializable隔離級別(幸運的是幻影讀問題一般情況下不嚴重)

悲觀鎖的實現,往往依靠資料庫提供的鎖機制(也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性,否 則,即使在本系統中實現了加鎖機制,也無法保證外部系統不會修改資料)。

實現方式

jdbc方式:在jdbc中使用悲觀鎖,需要使用select for update語句,假如我們系統中有乙個account的類,我們可 以採用如下的方式來進行:

select * from account where ...(where condition).. for update.

當使用了for update語句後,每次在讀取或者載入一條記錄的時候,都會鎖住被載入的記錄,那麼當其他事務如果要

更新或者是載入

此條記錄就會因為不能獲得鎖而阻塞,這樣就避免了不可重複讀以及髒讀的問題,但是其他事務還是 可以插入和刪除記錄,這樣也許同乙個事務中的兩次讀取會得到不同的結果集,但是這不是悲觀鎖鎖造成的問題,這 是我們資料庫隔離級別所造成的問題。

最後還需要注意的一點就是每個衝突的事務中,我們必須使用select for update 語句來進行資料庫的訪問,如果一 些事務沒有使用select for update語句,那麼就會很容易造成錯誤,這也是採用jdbc進行悲觀控制的缺點。

樂觀鎖【optimistic locking】

樂觀鎖是在同乙個資料庫事務中我們常採取的策略,因為

它能使得我們的系統保持高的效能的情況下,提高很好的併發 訪問控制。樂觀鎖,顧名思義就是保持一種樂觀的態度,我們

認為系統中的事務併發更新不會很頻繁,即使衝突了也沒事, 大不了重新再來一次。它的基本思想就是每次提交乙個事務更新時,我們想看看要修改的東西從上次讀取以後有沒有被其 它事務修改過,如果修改過,那麼更新就會失敗。(因此能夠解決第二類丟失修改問題)

因為樂觀鎖其實並不會鎖定任何記錄,所以如果我們資料庫的事務隔離級別設定為讀取已提交或者更低的隔離界別,那麼 是不能避免不可重複讀問題的(因為此時讀事務不會阻塞其它事務),所以採用樂觀鎖的時候,系統應該要容許不可重複 讀問題的出現。

需要注意的是,樂觀鎖機制往往基於系統中的資料儲存邏輯,因此也具備一定的侷限性,由於樂觀鎖機制是在我們的系統中 實現,來自外部系統的使用者更新操作不受我們系統的控制,因此可能會造成髒資料被更新到資料庫中。在系統設計階段,我 們應該充分考慮到這些情況出現的可能性,並進行相應調整(如將樂觀鎖策略在資料庫儲存過程中實現,對外只開放基於此 儲存過程的資料更新途徑,而不是將資料庫表直接對外公開)。

實現方式:

大多是基於資料版本 ( version )記錄機制實現。何謂資料版本?即為資料增加乙個版本標識,在基於資料庫表的版本解 決方案中,一般是通過為資料庫表增加乙個 「version」 欄位來實現。 

讀取出資料時,將此版本號一同讀出,之後更新時,對此版本號加一。此時,將提 交資料的版本資料與資料庫表對應記錄的 當前版本資訊進行比對,如果提交的資料 版本號大於資料庫表當前版本號,則予以更新,否則認為是過期資料。

假如系統中有乙個account的實體類,我們在account中多加乙個version欄位,那麼我們jdbc sql語句將如下寫:

select a.version....from account as a where (where condition..)

update account set version = version+1.....(another field) where version =?...(another contidition)

樂觀鎖與悲觀鎖

悲觀鎖 pessimistic locking 顧名思義就是採用一種悲觀的態度來對待事務併發問題,我們認為系統中的併發更新會非常頻繁,並且事務失敗了以後重來的開銷很大,這樣以來,我們就需要採用真正意義上的鎖來進行實現。悲觀鎖的基本思想就是每次乙個事務讀取某一條記錄後,就會把這條記錄鎖住,這樣 其它的...

樂觀鎖與悲觀鎖

鎖 locking 這個概念在我們學習多執行緒的時候曾經接觸過,其實這裡的鎖和多執行緒裡面處理併發的鎖是乙個道理,都是暴力的把資源歸為自己所有。這裡我們用到鎖的目的就是通過一些機制來保證一些資料在某個操作過程中不會被外界修改,這樣的機制,在這裡,也就是所謂的 鎖 即給我們選定的目標資料上鎖,使其無法...

樂觀鎖與悲觀鎖

悲觀鎖 pessimistic lock 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。傳統的關係型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。樂觀鎖 optim...