日韩黑丝制服一区视频播放|日韩欧美人妻丝袜视频在线观看|九九影院一级蜜桃|亚洲中文在线导航|青草草视频在线观看|婷婷五月色伊人网站|日本一区二区在线|国产AV一二三四区毛片|正在播放久草视频|亚洲色图精品一区

分享

mysql樂(lè)觀鎖和悲觀鎖詳解

 Coder編程 2022-02-13

mysql樂(lè)觀鎖和悲觀鎖詳解

相信很多朋友在面試的時(shí)候,都會(huì)被問(wèn)到樂(lè)觀鎖和悲觀鎖的問(wèn)題,如果不清楚其概念和用法的情況下,相信很多朋友都會(huì)感覺(jué)很懵逼,那么面試的結(jié)果也就不言而喻了。
那么樂(lè)觀鎖和悲觀鎖到底是個(gè)什么東西,用它能來(lái)做什么呢?
                相信大家都遇到這種場(chǎng)景,當(dāng)很多人(一兩個(gè)人估計(jì)不行)同時(shí)對(duì)同一條數(shù)據(jù)做修改的時(shí)候,那么數(shù)據(jù)的最終結(jié)果是怎樣的呢?
這也就是我們說(shuō)的并發(fā)情況,這樣會(huì)導(dǎo)致以下兩種結(jié)果:

  1. 更新錯(cuò)誤,你修改之后的數(shù)據(jù)可能被別人覆蓋了,導(dǎo)致你很懵逼,甚至懷疑自己開(kāi)發(fā)的功能是否有問(wèn)題;
  2. 臟讀,數(shù)據(jù)更新錯(cuò)誤,導(dǎo)致讀數(shù)據(jù)也是錯(cuò)的,查詢出一些默認(rèn)奇妙的數(shù)據(jù),看到的不是你自己修改的結(jié)果。

這樣的問(wèn)題怎么解決呢?于是乎,鎖就這樣產(chǎn)生了,鎖分為樂(lè)觀鎖和悲觀鎖,它的目的是用來(lái)解決并發(fā)控制的問(wèn)題。
MyISAM引擎不支持事務(wù),所以不考慮它有樂(lè)觀鎖和悲觀鎖概念。MyISAM只有表鎖,鎖又分為讀鎖和寫鎖。在這里我們只討論InnoDB引擎。
需要注意的是,樂(lè)觀鎖和悲觀鎖并不是解決并發(fā)控制的唯一手段(也可以使用消息中間件kafka,MQ之類的作為緩沖等等),而且樂(lè)觀鎖和悲觀鎖并不僅限制在mysql中使用,它是一種概念,很多其他的應(yīng)用,如redis,memcached等,只要存在并發(fā)情況的,都可以應(yīng)用這種概念,只是方式上有些差別而已。


一、樂(lè)觀鎖
樂(lè)觀鎖,簡(jiǎn)單地說(shuō),就是從應(yīng)用系統(tǒng)層面上做并發(fā)控制,去加鎖。
實(shí)現(xiàn)樂(lè)觀鎖常見(jiàn)的方式:版本號(hào)version
實(shí)現(xiàn)方式,在數(shù)據(jù)表中增加版本號(hào)字段,每次對(duì)一條數(shù)據(jù)做更新之前,先查出該條數(shù)據(jù)的版本號(hào),每次更新數(shù)據(jù)都會(huì)對(duì)版本號(hào)進(jìn)行更新。在更新時(shí),把之前查出的版本號(hào)跟庫(kù)中數(shù)據(jù)的版本號(hào)進(jìn)行比對(duì),如果相同,則說(shuō)明該條數(shù)據(jù)沒(méi)有被修改過(guò),執(zhí)行更新。如果比對(duì)的結(jié)果是不一致的,則說(shuō)明該條數(shù)據(jù)已經(jīng)被其他人修改過(guò)了,則不更新,客戶端進(jìn)行相應(yīng)的操作提醒。
使用版本號(hào)實(shí)現(xiàn)樂(lè)觀鎖
使用版本號(hào)時(shí),可以在數(shù)據(jù)初始化時(shí)指定一個(gè)版本號(hào),每次對(duì)數(shù)據(jù)的更新操作都對(duì)版本號(hào)執(zhí)行+1操作。并判斷當(dāng)前版本號(hào)是不是該數(shù)據(jù)的最新的版本號(hào)。 

//1.查詢出商品信息 

select status,version from t_goods where id=#{id} 

//2.根據(jù)商品信息生成訂單 

//3.修改商品status為2 

update t_goods 

set status=2,version=version+1 

where id=#{id} and version=#{version};

注意第二個(gè)事務(wù)執(zhí)行update時(shí),第一個(gè)事務(wù)已經(jīng)提交了,所以第二個(gè)事務(wù)能夠讀取到第一個(gè)事務(wù)修改的version。

下面這種極端的情況:

我們知道MySQL數(shù)據(jù)庫(kù)引擎InnoDB,事務(wù)的隔離級(jí)別是Repeatable Read,因此是不會(huì)出現(xiàn)臟讀、不可重復(fù)讀。
在這種極端情況下,第二個(gè)事務(wù)的update由于不能讀取第一個(gè)事務(wù)未提交的數(shù)據(jù)(第一個(gè)事務(wù)已經(jīng)對(duì)這一條數(shù)據(jù)加了排他鎖,第二個(gè)事務(wù)需要等待獲取鎖),第二個(gè)事務(wù)獲取了排他鎖后,會(huì)發(fā)現(xiàn)version已經(jīng)發(fā)生了改變從而提交失敗。

二、悲觀鎖
悲觀鎖,簡(jiǎn)單地說(shuō),就是從數(shù)據(jù)庫(kù)層面上做并發(fā)控制,去加鎖。
悲觀鎖的實(shí)現(xiàn)方式有兩種:共享鎖(讀鎖)排它鎖(寫鎖)
共享鎖(IS鎖),實(shí)現(xiàn)方式是在sql后加LOCK IN SHARE MODE,比如SELECT ... LOCK IN SHARE MODE,即在符合條件的rows上都加了共享鎖,這樣的話,其他session可以讀取這些記錄,也可以繼續(xù)添加                       IS鎖,但是無(wú)法修改這些記錄直到你這個(gè)加鎖的session執(zhí)行完成(否則直接鎖等待超時(shí))。
排它鎖(IX鎖),實(shí)現(xiàn)方式是在sql后加FOR UPDATE,比如SELECT ... FOR UPDATE ,即在符合條件的rows上都加了排它鎖,其他session也就無(wú)法在這些記錄上添加任何的S鎖或X鎖。如果不存在一致性非                         鎖定讀的話,那么其他session是無(wú)法讀取和修改這些記錄的,但是innodb有非鎖定讀(快照讀并不需要加鎖),for update之后并不會(huì)阻塞其他session的快照讀取操作,除了select ...lock in share mode和select ... for update這種顯示加鎖的查詢操作。

通過(guò)對(duì)比,發(fā)現(xiàn)for update的加鎖方式無(wú)非是比lock in share mode的方式多阻塞了select...lock in share mode的查詢方式,并不會(huì)阻塞快照讀

mysql InnoDB引擎默認(rèn)的修改數(shù)據(jù)語(yǔ)句:update,delete,insert都會(huì)自動(dòng)給涉及到的數(shù)據(jù)加上排他鎖,select語(yǔ)句默認(rèn)不會(huì)加任何鎖類型。

在Java中,synchronized的思想也是悲觀鎖。

以排它鎖為例

要使用悲觀鎖,我們必須關(guān)閉mysql數(shù)據(jù)庫(kù)的自動(dòng)提交屬性,因?yàn)镸ySQL默認(rèn)使用auto commit模式,也就是說(shuō),當(dāng)你執(zhí)行一個(gè)更新操作后,MySQL會(huì)立刻將結(jié)果進(jìn)行提交。set autocommit=0; 

//0.開(kāi)始事務(wù) 

begin;/begin work;/start transaction; (三者選一就可以) 

//1.查詢出商品信息 

select status from t_goods where id=1 for update; 

//2.根據(jù)商品信息生成訂單 

insert into t_orders (id,goods_id) values (null,1); 

//3.修改商品status為2 

update t_goods set status=2; 

//4.提交事務(wù) 

commit;/commit work;

上面的查詢語(yǔ)句中,我們使用了select…for update的方式, 這樣就通過(guò)開(kāi)啟排他鎖的方式實(shí)現(xiàn)了悲觀鎖。此時(shí)在t_goods表中,id為1的 那條數(shù)據(jù)就被我們鎖定了,其它的事務(wù)必須等本次事務(wù)提交之后才能執(zhí)行。這樣我們可以保證當(dāng)前的數(shù)據(jù)不會(huì)被其它事務(wù)修改。

補(bǔ)充:
1.MyISAM在執(zhí)行查詢語(yǔ)句(SELECT)前,會(huì)自動(dòng)給涉及的所有表加讀鎖,在執(zhí)行更新操作 (UPDATE、DELETE、INSERT等)前,會(huì)自動(dòng)給涉及的表加寫鎖。
2.MySQL InnoDB默認(rèn)行級(jí)鎖。 行級(jí)鎖都是基于索引的,如果一條SQL語(yǔ)句用不到索引是不會(huì)使用行級(jí)鎖的,會(huì)使用表級(jí)鎖把整張表鎖住。
3.從上面對(duì)兩種鎖的介紹,我們知道兩種鎖各有優(yōu)缺點(diǎn),不可認(rèn)為一種好于另一種,像樂(lè)觀鎖適用于寫比較少的情況下(多讀場(chǎng)景),即沖突真的很少發(fā)生的時(shí)候,這樣可以省去了鎖的開(kāi)銷,加大了系統(tǒng)的整個(gè)吞吐量。但如果是多寫的情況,一般會(huì)經(jīng)常產(chǎn)生沖突,這就會(huì)導(dǎo)致上層應(yīng)用會(huì)不斷的進(jìn)行retry,這樣反倒是降低了性能,所以一般多寫的場(chǎng)景下用悲觀鎖就比較合適。

參考:
http://www.cnblogs.com/exceptioneye/p/5373477.html

 

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多