第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

首頁 慕課教程 SQL 入門教程 SQL 入門教程 實戰(zhàn)3:如何使用樂觀鎖

實戰(zhàn)3:如何使用樂觀鎖

1. 前言

一節(jié)中,我們從粒度管理兩個角度來闡述了鎖。如果你還不熟悉鎖,請先閱讀該小節(jié),再來進(jìn)行本小節(jié)的學(xué)習(xí)。

本小節(jié)我們將繼續(xù)深挖,以開發(fā)者和實戰(zhàn)的角度來談鎖。

2. 為什么需要鎖

2.1 什么是數(shù)據(jù)競爭

在本節(jié)的開頭,我們來談一談為什么開發(fā)程序需要使用鎖?如果你有一點(diǎn)并發(fā)編程的基礎(chǔ),又或者對多線程有一點(diǎn)熟悉,那么你肯定知道答案,那就是數(shù)據(jù)競爭。

2.2 數(shù)據(jù)競爭實例

我們舉一個生活的例子。在中學(xué)的時候,教室的前面會放上一塊小黑板,小黑板上會記載某一天上交作業(yè)或誰誰誰打掃衛(wèi)生之類的。那塊小黑板是所有同學(xué)都可使用的,只要你有事情要公布,就可以寫在上面。

那么問題來了,假設(shè)同學(xué)A用小黑板寫上明天要上交的作業(yè),此時同學(xué)B也需要寫上明天值日的同學(xué),對于AB來說,他們之間存在競爭關(guān)系,而小黑板就是競爭點(diǎn)。

直觀上來說,如果AB早到,那么A就可以占有小黑板,換言之A給小黑板加上了一把鎖,B不能使用小黑板。A寫完了,把小黑板再次放到了教室前,相當(dāng)于釋放了鎖,此時B才可書寫小黑板,即B拿到了鎖。

因此,鎖的出現(xiàn)是為了解決并發(fā)中存在的數(shù)據(jù)競爭問題。

3. 樂觀鎖和悲觀鎖

樂觀悲觀是兩種不同的態(tài)度,從名字上看,二者就是以開發(fā)者的態(tài)度作為邊界來分類的。

樂觀鎖認(rèn)為,同一數(shù)據(jù)在并發(fā)條件下,發(fā)生沖突是小概率事件,因此我們不加鎖,而是加上版本號判斷修改是否成功。

悲觀鎖認(rèn)為,同一數(shù)據(jù)在并發(fā)條件下,沖突是大概率事件,因此我們必須先加鎖,不允許別人修改。

悲觀鎖和樂觀鎖其實是一種思想,主要取決于開發(fā)者對待它的態(tài)度。在這一小節(jié)中,里面談到的所有鎖宏觀上(可能實現(xiàn)的思想是樂觀鎖)來說都是悲觀鎖,因此一旦加鎖,都會鎖定數(shù)據(jù),直到解鎖才會釋放。

3.1 樂觀鎖實施方案

樂觀鎖不全依賴于數(shù)據(jù)庫,一般情況下我們都是在代碼層面上來完成它的,主流的設(shè)計思路是這樣的:

我們在數(shù)據(jù)表中添加一個字段version,version 代表版本號,字段類型為整型。當(dāng)我們獲取數(shù)據(jù)時,假設(shè)得到它的version字段為n,執(zhí)行完其它操作對該數(shù)據(jù)進(jìn)行更新時,會執(zhí)行UPDATE ... SET version=n+1 WHERE version=n。

如果在更新時,數(shù)據(jù)已經(jīng)被別人更新過了,那么該數(shù)據(jù)的version字段已經(jīng)不是n了,那么此時修改就會失敗,反之修改就會成功。

可以看到,樂觀鎖就像它的名稱一樣樂觀,適合數(shù)據(jù)讀多寫少的場景,因為實際上并沒鎖住數(shù)據(jù),所以性能十分可觀;而悲觀鎖則與之相反,適合寫多讀少的場景,盲目的排他性一定程度上會大幅影響性能。

4. 實踐

4.1 樂觀鎖數(shù)據(jù)表

樂觀鎖的使用十分廣泛,我們也推薦你在實際的開發(fā)中使用樂觀鎖,接下來,我們以一個例子來詳細(xì)的說明一下樂觀鎖。

我們新建一個測試數(shù)據(jù)表 imooc_order :

DROP TABLE IF EXISTS imooc_order;
CREATE TABLE imooc_order
(
  id int PRIMARY KEY,
  price decimal(10,2),
  -- version 字段作為樂觀鎖版本控制位
  version int NOT NULL DEFAULT 0
);
INSERT INTO imooc_order(id,price,version)
VALUES (1,23.2,1);

注意: 我們已經(jīng)在表中添加了 version 字段

4.2 樂觀鎖實例

imooc_order表存放了訂單信息(簡略信息),而訂單的價格并非一成不變的,它可能會同時被多個人改變。

那么如何能夠安全地修改它的價格,且不會跟別人沖突了。

現(xiàn)在默認(rèn)有兩個人,現(xiàn)在拿到了id1的訂單,想要修改它的價格:

SELECT * FROM imooc_order WHERE id = 1; 

拿到的同時,也同樣拿到了訂單數(shù)據(jù),且訂單此時的價格為23.2,版本號為1。

決定修改訂單的價格為33.3,于是他執(zhí)行了如下語句:

UPDATE imooc_order SET version = 1 + 1, price=33.3 WHERE id = 1 AND version = 1;

執(zhí)行成功了,而此時也需要修改價格,但是他并不知道價格已經(jīng)修改:

UPDATE imooc_order SET version = 1 + 1, price=22.1 WHERE id = 1 AND version = 1;

很明顯,修改失敗了,因為在他修改價格之前,以微弱的速度優(yōu)勢已經(jīng)修改了價格,且修改了 version字段,此時 version等于2

提交 SQL 語句時,Where 中明確的寫到 version 等于 1。即使乙修改失敗,但是數(shù)據(jù)仍然是正確的,完全可以在失敗的情況下重復(fù)獲取一次數(shù)據(jù)再修改。

如下圖所示:
圖片描述

4.3 樂觀鎖總結(jié)

可以看到,樂觀鎖雖然有缺陷,它會使更新失敗,因此必須重復(fù)獲取數(shù)據(jù)然后重試,但是它保證了數(shù)據(jù)的正確性和完整性。在讀多寫少的場景下,樂觀鎖不會出現(xiàn)太多的重試,當(dāng)然如果出現(xiàn)了很多重試,證明場景已經(jīng)可能不是讀多寫少了,可以嘗試換方案了。

樂觀鎖的實現(xiàn)也頗為簡單,不需要任何第三方依賴,你完全可以自己直接實現(xiàn),不過仍然有一些第三方框架提供了開箱即用的樂觀鎖,你可以根據(jù)自己的使用語言和生態(tài)去查找相應(yīng)的樂觀鎖框架。

5. 小結(jié)

  • 樂觀鎖和悲觀鎖同等重要,樂觀鎖是很多高并發(fā)場景下的基石。
  • 大多數(shù)時候,程序使用的都是悲觀鎖,如常見的自旋鎖。
  • 樂觀鎖與悲觀鎖都是一種思路,熟悉并掌握該思路,任何面試都攔不到你。