樂觀鎖,悲觀鎖

2021-10-12 01:43:40 字數 2796 閱讀 7905

基於redis的分布式鎖;

一、悲觀鎖

1、排它鎖,當事務在運算元據時把這部分資料進行鎖定,直到操作完畢後再解鎖,其他事務操作才可操作該部分資料。這將防止其他程序讀取或修改表中的資料。

2、實現:大多數情況下依靠資料庫的鎖機制實現

一般使用 select ...for update 對所選擇的資料進行加鎖處理,例如select * from account where name=」max」 for update, 這條sql 語句鎖定了account 表中所有符合檢索條件(name=」max」)的記錄。本次事務提交之前(事務提交時會釋放事務過程中的鎖),外界無法修改這些記錄。
二、樂觀鎖

1、如果有人在你之前更新了,你的更新應當是被拒絕的,可以讓使用者重新操作。

2、實現:大多數基於資料版本(version)記錄機制實現

具體可通過給表加乙個版本號或時間戳字段實現,當讀取資料時,將version欄位的值一同讀出,資料每更新一次,對此version值加一。當我們提交更新的時候,判斷當前版本資訊與第一次取出來的版本值大小,如果資料庫表當前版本號與第一次取出來的version值相等,則予以更新,否則認為是過期資料,拒絕更新,讓使用者重新操作。
樂觀鎖的實現:

使用版本控制字段,再利用行鎖的特性實現樂觀鎖,如下

有一張訂單表order,有欄位id、order_no、 price, 為實現樂觀鎖控制,新增version欄位,預設值為0

order

id 1

order_no 123456

price 5

version 0

假設兩個人同時進來修改該條資料,操作為:

1. 先查詢該資料   select *

from order where id =

12. 修改該條資料 update order set price =

1 where id =

1

如果兩個人同時查詢到該條資料price = 5, 可以執行update操作, 但任意一方還沒執行update操作,那麼最後雙方都執行update,導致資料被修改兩次,產生髒資料 !

使用version欄位控制版本後:

兩人先查詢該資料 select * from order where id = 1

此時兩人查詢到的資料一樣,id = 1, price = 5, order_no = 123456, version = 0

兩人都發現該條資料price = 5, 符合update條件,第一人執行update(因為mysql行鎖的特性,兩人不可能同時修改一條資料,所以update同一條資料的時候,是有先後順序的,只有在第乙個執行完update,才能釋放行鎖,第二個繼續進行update):

update order set price =

1, version = version +

1 where id =

1 and version =

0

執行完成後,version字段值將變成1, 第二人執行update:

update order set price =

1, version = version +

1 where id =

1 and version =

0

此時的version的值已經被修改為1,所以第二人修改失敗,實現樂觀鎖控制。

死鎖的處理:

資料庫使用樂觀鎖導致產生死鎖:

事務a

update order set price =

1 where id =

1update order set price =

2 where id =

2

事務b

update order set price =

1 where id =

2update order set price =

2 where id =

1

假設在兩個事務中有以上兩個操作,同時修改order表中兩條資料

事務a在執行完第一條update的時候,剛好事務b也執行完第一條update

此時, 事務a中order表中的id = 1的行被鎖住, 事務b中order表中id = 2的行被鎖住,兩個事務繼續往下執行

事務a中第二條update執行需要order表中id = 2的行資料,而事務b中第二條update執行需要id = 1的行資料, 兩條update往下執行的條件都需要對方事務中已經被鎖住的行,於是陷入無限等待,形成死鎖。

解決死鎖的產生:

指定鎖的執行順序,比如把以上兩事務稍作修改

事務a

update order set price =

2 where id =

2update order set price =

1 where id =

1

事務b

update order set price =

1 where id =

2update order set price =

2 where id =

1

事務a執行第一條update時,id = 2 的行被鎖住,此時,事務b想修改id = 2的行,只能等待事務a執行完成,當事務a執行完成時,事務b再執行, 這樣就不會產生死鎖了。

悲觀鎖樂觀鎖

1 悲觀鎖,正如其名,它指的是對資料被外界 包括本系統當前的其他事務,以及來自外部系統的事務處理 修改持保守態度,因此,在整個資料處理過程中,將資料處於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制 也只有資料庫層提供的鎖機制才能真正保證資料訪問的排他性,否則,即使在本系統中實現了加鎖機制,也無...

樂觀鎖 悲觀鎖

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

樂觀鎖 悲觀鎖

樂觀鎖 悲觀鎖 悲觀鎖 pessimistic locking 悲觀鎖,正如其名,它指的是對資料被外界 包括本系統當前的其他事務,以及來自外部系統的事務處理 修改持保守態度,因此,在整個資料處理過程中,將資料處於鎖定狀態。悲觀鎖的實現,往往依靠資料庫提供的鎖機制 也只有資料庫層提供的鎖機制才能真正保...