国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

MySQL樂觀鎖與悲觀鎖

這篇具有很好參考價值的文章主要介紹了MySQL樂觀鎖與悲觀鎖。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

說明

遇見并發(fā)情況,需要保證數(shù)據(jù)的準(zhǔn)確性,也就是與正確的預(yù)期一致,此時就會用到鎖。
鎖是在并發(fā)下控制程序的執(zhí)行邏輯,以此來保證數(shù)據(jù)按照預(yù)期變動。
如果不加鎖,并發(fā)情況下的可能數(shù)據(jù)不一致的情況,這是個概率問題。

樂觀鎖CAS

簡介

樂觀鎖很樂觀,假設(shè)數(shù)據(jù)一般情況不會造成沖突,屬于程序?qū)用娴倪壿嬫i,在數(shù)據(jù)進(jìn)行更新時,才進(jìn)行鎖的檢測。是通過添加一個版本號的方式實現(xiàn)的,每當(dāng)數(shù)據(jù)這一行所在的數(shù)據(jù)發(fā)生變化,則對應(yīng)的版本號+1,更新數(shù)據(jù)時,將版本號作為查詢條件。
至于是否要加事務(wù),看寫操作單條數(shù)據(jù)還是寫操作多條數(shù)據(jù)。

注意:網(wǎng)上很多解決方案用時間戳來做version字段,我持反對意見,并發(fā)可能是一瞬間的事,不到一秒就有好多請求,用時間戳粒度太大,用隨機(jī)字符串都比用這個強(qiáng)。

用法

#示例
update test set score = score + 1 where id = 1
#優(yōu)化為,這種簡單,但是會有ABA的問題:
select score as old_score from test where id  = 1;
update test set score = score + 1 where id = 1 and score = old_score;
#或者添加一個version字段,這種不存在ABA的問題
select version from test where id  = 1;
update test set score = score + 1 where id = 1 and version = version;

適用場景

  1. 讀多寫少:由于并發(fā)寫操作較少,樂觀鎖的修改數(shù)據(jù)受影響行數(shù)為0概率也較低。
  2. 允許一定量的重試或不需要重試的場景:這個要根據(jù)業(yè)務(wù),否則來回重試會降低性能。

優(yōu)點

實現(xiàn)簡單:樂觀鎖在代碼上就可以實現(xiàn),不需要額外對數(shù)據(jù)庫額外操作。
無死鎖風(fēng)險:悲觀鎖有死鎖風(fēng)險,樂觀鎖沒有。
無需重試情況下,性能較高:樂觀鎖機(jī)制在并發(fā)訪問情況下,不需要像悲觀鎖那樣阻塞其他事務(wù),提供了更高的并發(fā)性能,前提當(dāng)前業(yè)務(wù)需求能容忍寫操作失敗的情況。

缺點

并發(fā)沖突:多加了一個where條件,只能保證數(shù)據(jù)最終不會出錯,不能保證每條寫操作的SQL都執(zhí)行成功(也就是受影響行數(shù)>0)。
不提供強(qiáng)一致性:強(qiáng)一致性要求數(shù)據(jù)的狀態(tài)在任何時刻都保持一致,悲觀鎖是到寫操作那一步才去驗證,期間只是做了個where條件的過濾。
ABA問題:一個字段的值在請求X中查詢出來是A,后續(xù)代碼實現(xiàn)樂觀鎖,因為并發(fā)量大,同時過來一個Y請求,將A值改成了B,因為一些業(yè)務(wù)原因又改成了A,整個過程雖然不影響請求X的結(jié)果,且能正常執(zhí)行,但是聯(lián)合其它數(shù)據(jù),這個情況是否符合業(yè)務(wù)場景,不好說,所以最好的解決方案,就是專門做一個version字段,且不會與之前的version重復(fù),即可,把這個version字段作為where條件,而不是存A或者B字段的所在字段作為where條件。

悲觀鎖

簡介

悲觀鎖比較悲觀,假設(shè)數(shù)據(jù)一定會造成沖突,屬于MySQL層面的鎖。通過加鎖阻塞其他事務(wù),悲觀鎖可以保證在任何時刻,只有一個事務(wù)能夠修改或訪問共享資源,從而實現(xiàn)了強(qiáng)一致性。這意味著在悲觀鎖機(jī)制下,每個事務(wù)的讀寫操作都是有序、線性的。
需要事務(wù)的參與。

用法

在事務(wù)中的查詢語句添加for update即可。

如果此時執(zhí)行了三行內(nèi)容沒有commit,再次執(zhí)行update test set score = score + 1 where id = 1;則處于阻塞狀態(tài),需要等commit之后,才能執(zhí)行。
start transaction;
select * from test where id = 1 for update;
update test set score = score + 1 where id = 1;
commit;

適用場景

寫多寫操作的前提,是保證數(shù)據(jù)不出錯,悲觀鎖的機(jī)制很符合。

優(yōu)點

強(qiáng)一致性:基于事務(wù)又加鎖,一致性可以保證。
實現(xiàn)簡單:在事務(wù)中for update即可,開發(fā)者不需要在這上面關(guān)注太多。

缺點

死鎖風(fēng)險:悲觀鎖在使用不當(dāng)?shù)那闆r下可能導(dǎo)致死鎖。如果多個事務(wù)持有鎖并相互等待對方釋放鎖的情況發(fā)生,就可能發(fā)生死鎖。
性能較低:悲觀鎖通常需要在整個事務(wù)過程中鎖定資源,這可能導(dǎo)致其他事務(wù)阻塞。

模擬實現(xiàn)

前置準(zhǔn)備

#創(chuàng)建一個非常簡單的表,并插入一條數(shù)據(jù)
CREATE TABLE `test` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `score` int(11) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

INSERT INTO `test` (`id`, `score`) VALUES (1, 0);

需求模擬

查詢test表id為1的數(shù)據(jù),檢測到score值為0,則自增,否則終止。

不加鎖實現(xiàn)

為了提升性能,使用了原生PDO操作MySQL去實現(xiàn)。

//連接數(shù)據(jù)庫
$pdo = new \PDO("mysql:host=127.0.0.1;port=3306;dbname=temp;", 'root', 'root');
$pdo->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION);
$pdo->query('set names utf8mb4');

//查詢
$query = $pdo->query('select score from test');
$query->setFetchMode(\PDO::FETCH_ASSOC);
$res = $query->fetchALL();


if($res[0]['score'] == 0) {
    $res = $pdo->exec('update test set score = score + 1 where id = 1');
    var_dump($res);
}

并發(fā)模擬

用ab壓測,發(fā)現(xiàn)效果不明顯,可能是ab工具不夠力或者電腦線程數(shù)量太少導(dǎo)致。
這里用的是ApiPost的壓測工具。500個并發(fā)去多次壓測一輪,發(fā)現(xiàn)score值是3,證明確實因為并發(fā)造成了與預(yù)期結(jié)果不一致的情況。

樂觀鎖解決方案(忽略ABA問題)

#將sql改為如下所示,實測多次,score最大值是1
#注意這種行為,只能保證score的值最大是1,無法保證執(zhí)行這個SQL的時候,受影響行數(shù)>0
update test set score = score + 1 where id = 1 and score = 0

悲觀鎖解決方案

$pdo = new \PDO("mysql:host=127.0.0.1;port=3306;dbname=temp;", 'root', 'root');
$pdo->setAttribute(\PDO::ATTR_ERRMODE,\PDO::ERRMODE_EXCEPTION);
$pdo->query('set names utf8mb4');

$redis = new Redis;
$redis->connect('127.0.0.1', 6379);

try {
    $pdo->beginTransaction();

    $stmt = $pdo->prepare("select * from test where id = 1 for update");
    $stmt->execute();
    $res = $stmt->fetch(PDO::FETCH_ASSOC);

    if($res['score'] == 0) {
        $stmt = $pdo->prepare("UPDATE test SET score = (score + 1) where id  = 1");
        $stmt->execute();
        $pdo->commit();
        $redis->incr('commit');
    } else {
        $redis->incr('rollback');
        $pdo->rollBack();
    }
} catch (PDOException $e) {
    $pdo->rollBack();
}

// 關(guān)閉數(shù)據(jù)庫連接
$pdo = null;

500個并發(fā)壓測一輪,查看redis數(shù)據(jù),commit數(shù)量為1,其余499全部都是rollback,這么多的回滾不代表大錯特錯(演示效果),而是因為第一個事務(wù)執(zhí)行成功后,再執(zhí)行其它事務(wù),正因為一個一個排隊,就不會出現(xiàn)同時讀取多個score值為0的情況了。文章來源地址http://www.zghlxwxcb.cn/news/detail-819482.html

到了這里,關(guān)于MySQL樂觀鎖與悲觀鎖的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實不符,請點擊違法舉報進(jìn)行投訴反饋,一經(jīng)查實,立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費用

相關(guān)文章

  • 【樂觀鎖與悲觀鎖】—— 每天一點小知識

    【樂觀鎖與悲觀鎖】—— 每天一點小知識

    ?????????????????????????????????????????????????????????????????????????????? ?? 樂觀鎖與悲觀鎖 color{#FF1493}{樂觀鎖與悲觀鎖} 樂觀鎖與悲觀鎖 ?? ????????? ?? 仰望天空,妳我亦是行人.? ?? 個人主頁——微風(fēng)撞見云的博客??

    2024年02月08日
    瀏覽(66)
  • Mysql--技術(shù)文檔--悲觀鎖、樂觀鎖-《控制并發(fā)機(jī)制簡單認(rèn)知、深度理解》

    ????????首先在談到并發(fā)控制機(jī)制的時候,我們通常會提及兩種重要的鎖策略。悲觀鎖(Pessimistic Locking)和樂觀鎖(Optimistic Locking)。這兩個是在處理并發(fā)的時候采取的不同思路。 ????????悲觀鎖: 悲觀鎖機(jī)制認(rèn)為并發(fā)操作中會有沖突,因此默認(rèn)情況下假設(shè)會出現(xiàn)并

    2024年02月10日
    瀏覽(24)
  • JavaEE 初階篇-深入了解 CAS 機(jī)制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級鎖與重量級鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等)

    JavaEE 初階篇-深入了解 CAS 機(jī)制與12種鎖的特征(如樂觀鎖和悲觀鎖、輕量級鎖與重量級鎖、自旋鎖與掛起等待鎖、可重入鎖與不可重入鎖等等)

    ??博客主頁:?【 小扳_-CSDN博客】 ?感謝大家點贊??收藏?評論? 文章目錄 ? ? ? ? 1.0 樂觀鎖與悲觀鎖概述 ? ? ? ? 1.1 悲觀鎖(Pessimistic Locking) ? ? ? ? 1.2 樂觀鎖(Optimistic Locking) ? ? ? ? 1.3 區(qū)別與適用場景 ? ? ? ? 2.0 輕量級鎖與重量級鎖概述 ? ? ? ? 2.1 真正加

    2024年04月16日
    瀏覽(41)
  • Java并發(fā)(十四)----悲觀互斥與樂觀重試

    1. 悲觀互斥 互斥實際是悲觀鎖的思想 例如,有下面取款的需求 用互斥來保護(hù) 2. 樂觀重試 另外一種是樂觀鎖思想,它其實不是互斥

    2024年02月15日
    瀏覽(24)
  • MySQL悲觀鎖并發(fā)控制實現(xiàn)案例

    實體層 Mapper層 PointMapper.java代碼 業(yè)務(wù)層 web接口層

    2024年02月12日
    瀏覽(21)
  • 悲觀鎖&樂觀鎖

    1.悲觀鎖 悲觀鎖介紹(百科): 悲觀鎖,正如其名,它指的是對數(shù)據(jù)被外界(包括本系統(tǒng)當(dāng)前的其他事務(wù),以及來自外部系統(tǒng)的事務(wù)處理)修改持保守態(tài)度,因此,在整個數(shù)據(jù)處理過程中,將數(shù)據(jù)處于鎖定狀態(tài)。悲觀鎖的實現(xiàn),往往依靠數(shù)據(jù)庫提供的鎖機(jī)制(也只有數(shù)據(jù)庫層

    2024年02月08日
    瀏覽(25)
  • django實現(xiàn)悲觀鎖樂觀鎖

    前期準(zhǔn)備 1.原生mysql悲觀鎖 2.orm實現(xiàn)上述(悲觀鎖)? 3 樂觀鎖秒殺--》庫存還有,有的人就沒成功 ?

    2024年02月12日
    瀏覽(26)
  • 悲觀鎖和樂觀鎖(易懂)

    這里可以把悲觀鎖看作悲觀的人,啥事都往最壞的方向想。樂觀鎖看作樂觀的人,啥事都往最好的方向想。 首先,說一下悲觀鎖。 悲觀鎖就是假設(shè)并發(fā)情況下一定會有其他線程來修改數(shù)據(jù),因此在處理數(shù)據(jù)之前,先將數(shù)據(jù)鎖住,確保其他線程不能進(jìn)行修改 。感覺像一個過于

    2024年02月08日
    瀏覽(23)
  • 悲觀鎖和樂觀鎖、緩存

    悲觀鎖和樂觀鎖、緩存

    悲觀鎖: 悲觀鎖的實現(xiàn)通常依賴于數(shù)據(jù)庫提供的機(jī)制,在整個處理的過程中數(shù)據(jù)處于鎖定狀態(tài),session的load方法有一個重載方法,該重載方法的第三個參數(shù)可以設(shè)置鎖模式,load(object.class , int id,LockMode.?),該方法的?就是具體的鎖模式。 樂觀鎖: 樂觀鎖使用版本號或者時間戳

    2024年02月09日
    瀏覽(20)
  • 什么是樂觀鎖和悲觀鎖?

    樂觀鎖和悲觀鎖是并發(fā)控制的兩種不同策略,用于在多線程環(huán)境下管理共享資源的訪問。它們有不同的思想和實現(xiàn)方式: 悲觀鎖(Pessimistic Locking) : 思想 :悲觀鎖的思想是,它假定在并發(fā)訪問中會發(fā)生沖突,因此在訪問共享資源之前會先加鎖,以防止其他線程訪問。悲觀

    2024年02月10日
    瀏覽(25)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包