樂觀鎖與悲觀鎖

2021-09-25 10:48:18 字數 2898 閱讀 8284

一、悲觀鎖

悲觀鎖(pessimistic lock),每次拿到資料時都會擔心被別人修改,所以每次在拿資料的時候都會上鎖,確保自己使用的過程中不會被被人修改,使用完後再釋放鎖。悲觀鎖常見的實現場景:

以第一種資料庫層的悲觀鎖為例,在關係型資料庫中,悲觀併發控制(pessimistic concurrency control, 簡寫為pcc)被稱為悲觀鎖,它是一種資料庫層的併發控制方法,如果乙個事務執行的操作對一行資料上了鎖,那只有當這個事務釋放鎖,其他事務才執行與該鎖衝突的操作。

本文使用mysql innodb做測試,mysql預設使用autocommit模式,也就是說執行乙個更新操作後,mysql會立即將結果提交,因此,為便於測試需要關閉自動提交模式.

開啟mysql-console1:

mysql> set autocommit=0;
建立的測試資料如下:

mysql> select * from user;

---+----+---------+-----+

| id | name | age |

+----+---------+-----+

| 1 | hehe | 29 |

| 2 | tonglin | 25 |

+----+---------+-----+

開啟並執行事務:

mysql> begin; # 同begin work/start transaction

mysql> select * from user where id=1 for update;

mysql> update user set age=100 where id=1;

此時,開啟mysql-console2,對同一行記錄進行查詢或修改:

mysql> select * from user where id=1;

---+----+------+-----+

| id | name | age |

+----+------+-----+

| 1 | hehe | 29 |

+----+------+-----+

1 row in set (0.00 sec)

mysql> update user set age=99 where id=1;

---

在mysql-console2上可以對id=1的記錄進行查詢,但修改操作會被阻塞,直到mysql-console1上的事務提交或回滾。

mysql-console1:

mysql> commit; # commit work,或回滾rollback
mysql-console2:

mysql> update user set age=99 where id=1;

---query ok, 1 row affected (0.00 sec)

二、樂觀鎖

樂觀鎖(optimistic lock),每次拿資料的時候完全不擔心被別人修改,所以每次拿資料的時候都不會上鎖,但是會在更新資料的時候判斷是否被別人修改過,期間資料可以被其他人讀取。悲觀鎖常見的實現場景:

仍然以資料庫為例,在關係型資料庫中,樂觀併發控制(optimistic concurrency control, 簡寫為occ)被稱為樂觀鎖。在提交資料庫更新前會檢查其他事務是否已經修改了資料,如果有更新,則當前提交的事務進行回滾。

首先為資料庫表增加version欄位:

mysql> select * from user;

---+----+---------+-----+---------+

| id | name | age | version |

+----+---------+-----+---------+

| 1 | hehe | 99 | 0 |

| 2 | tonglin | 25 | 0 |

+----+---------+-----+---------+

在執行更新前先查詢資料庫,將版本號version欄位一同讀出,資料每更新一次將version值加1。模擬併發的場景,假設兩個執行緒讀取了相同的記錄資料,並嘗試對相應主鍵(id=1)和版本號(version=1)的就進行修改,並將其版本號加1,這樣只有第乙個執行的執行緒可以執行成功,第二個執行緒執行時版本號已經變為2,因此更新失敗。

select * from user where id=1;

---+----+------+-----+---------+

| id | name | age | version |

+----+------+-----+---------+

| 1 | hehe | 1 | 1 |

+----+------+-----+---------+

mysql> update user set age=2, version=version+1 where id=1 and version=1;

---query ok, 1 row affected (0.01 sec)

rows matched: 1 changed: 1 warnings: 0

mysql> update user set age=3, version=version+1 where id=1 and version=1;

---query ok, 0 rows affected (0.00 sec)

rows matched: 0 changed: 0 warnings: 0

三、優缺點對比

兩種鎖各有優缺點,不能單純說哪個更好,需要根據具體業務場景決定使用哪一種鎖。 參考

悲觀鎖與樂觀鎖

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

樂觀鎖與悲觀鎖

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

樂觀鎖與悲觀鎖

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