一、什麼是悲觀鎖?什麼是樂觀鎖?
1)鎖(lock)
在介紹樂觀鎖和悲觀鎖之前,我們先介紹下鎖。
在日常生活中,我們經常接觸到鎖這個東西,比如家裡門上的鎖,自行車上的鎖,保險櫃上的鎖等,這些都是為了保障我們的財產安全而上的鎖。
而在程式中,鎖是一種保障資料安全的機制和手段。在多併發的情況,當同時多個請求修改相同的資料時,為了保障這種修改是安全的,會給這些資料加上鎖,來控制併發下的多個操作的執行順序。
本篇介紹的樂觀鎖和悲觀鎖是基於資料庫層面保障資料修改安全的鎖。
2)悲觀鎖(pessimistic concurrency control)
悲觀鎖,就是悲觀的鎖,對應於人類的悲觀情緒。悲觀鎖認為它保護的資料時是及其不安全的,每次只允許乙個事務對資料進行操作。當乙個事務拿到悲觀鎖後,其他事務就不能對該鎖住的資料就行修改,需要等待鎖被釋放為止。
3)樂觀鎖(optimistic concurrency control)
樂觀鎖,就是樂觀的鎖,對應於人類的樂觀情緒。樂觀鎖的「樂觀情緒」體現在,它認為資料是安全的,不會被頻繁的該動,所以允許多個事務對該資料進行操作。
樂觀鎖並不是無條件的允許多事務對資料進行操作的,其中一種方式是通過version 來控制事務對資料的修改。事務對資料修改前會對比事務修改資料的version值與資料庫中的version值是否一致,如果一致,則允許修改,並將資料庫中的修改資料庫中的version為version+1。
如上圖所示,事務1修改資料成功,並將資料庫中的version修改為version=version+1,則其他併發事務如果再去修改時會因為version值的不一致而導致修改失敗。
二、怎麼實現悲觀鎖?怎麼實現樂觀鎖?
悲觀鎖和樂觀鎖是用來控制併發下資料變動的順序問題。下面我們通過乙個小場景來模擬加悲觀鎖和樂觀鎖的過程,來直觀的感知下悲觀鎖和樂觀鎖。
場景:使用者a和使用者b,同時進入同一家賣口紅的**進行購買阿尼瑪口紅。
下面是product_tab結構和資料:
從表中可以看出阿尼瑪口紅的庫存是1,如果在不加鎖的情況下,如果使用者a和使用者b同時下單買阿尼瑪口紅,就會報錯。那怎麼解決這種報錯的情況呢?下面是悲觀鎖解鎖和樂觀鎖解決兩種方式。
1)悲觀鎖解決
我們使用的資料庫是mysql,儲存引擎是innodb。
利用悲觀鎖的解決思路是:
事務a在購買之前,先去查庫存,並給這條查詢資料加上悲觀鎖(行鎖),接著購買,並將庫存減1。
事務b在事務a提交之前查詢會因為悲觀鎖(行鎖)等待,如果鎖等待超時,會導致庫存查詢失敗;在事務a提交後獲得悲觀鎖(行鎖)後才能查庫存成功,這時候庫存是事務a購買之後的庫存是0,就會放棄購買。
那麼如何給阿瑪尼口紅也就是product_id=1這條資料加上悲觀鎖鎖呢?我們可以通過這個語句給product_id=1001的這行資料加上悲觀鎖:
select stock_num from product_tab where id = 1 for update;同時開啟兩個事務,事務a模擬使用者a的操作,事務b模擬使用者b的操作,他們的操作順序如下
2)樂觀鎖解決
樂觀鎖是通過版本號version來實現解決併發操作時資料操作的衝突的。所以我們需要給product_tab加上version欄位。表變動後的結構以及資料如下:
樂觀鎖的解決思路如下:
1、開啟兩個會話a和b(注意,不是事務,所以兩個會話操作沒有用到資料庫中的鎖)
2、會話a和b同時查詢阿尼瑪口紅的stock_num和version,都查出來stock_num=1,version=0;
3、會話a進行購買,購買前會檢查版本號,也就是檢查version是否為0,為0就購買,購買後stock_num=stock_num-1,version=version+1;會話a購買後進行查詢,可以看到這時候stock_num=0,version=1;
4、接著會話b進行購買,也就檢查版本號是否為0,因為這時候版本號已經被a置為1了,所以可以看到update操作後,0 rows effected。也就是b購買失敗。
會話操作如下:
三、樂觀鎖和悲觀鎖的優缺點
1)悲觀鎖
2)樂觀鎖
Mysql鎖機制之 樂觀鎖和悲觀鎖
悲觀鎖 pessimistic lock 顧名思義,就是很悲觀,每次去拿資料的時候都認為別人會修改,所以每次在拿資料的時候都會上鎖,這樣別人想拿這個資料就會block直到它拿到鎖。注 要使用悲觀鎖,我們必須關閉mysql資料庫的自動提交屬性,因為mysql預設使用autocommit模式,也就是說,...
悲觀鎖與樂觀鎖
悲觀鎖與樂觀鎖 悲觀鎖 pessimistic locking 顧名思義就是採用一種悲觀的態度來對待事務併發問題,我們認為系統中的併發更新會非常頻繁,並且事務失敗 了以後重來的開銷很大,這樣以來,我們就需要採用真正意義上的鎖來進行實現。悲觀鎖的基本思想就是每次一 個事務讀取某一條記錄後,就會把這條記...
樂觀鎖與悲觀鎖
悲觀鎖 pessimistic locking 顧名思義就是採用一種悲觀的態度來對待事務併發問題,我們認為系統中的併發更新會非常頻繁,並且事務失敗了以後重來的開銷很大,這樣以來,我們就需要採用真正意義上的鎖來進行實現。悲觀鎖的基本思想就是每次乙個事務讀取某一條記錄後,就會把這條記錄鎖住,這樣 其它的...