1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        Mysql的排他鎖和共享鎖

        共 2508字,需瀏覽 6分鐘

         ·

        2020-12-05 21:19

        今天看代碼看到有select name from user where id = 1 for update,有點(diǎn)懵逼,完全沒(méi)有見(jiàn)過(guò),只能說(shuō)自己見(jiàn)識(shí)少了,那就只能學(xué)習(xí)一下。先做一下基本知識(shí)了解:

        鎖的基本概念

          當(dāng)多事務(wù)爭(zhēng)取一個(gè)資源時(shí),有可能導(dǎo)致數(shù)據(jù)不一致,這個(gè)時(shí)候需要一種機(jī)制限制,并且將數(shù)據(jù)訪問(wèn)順序化,用來(lái)保證數(shù)據(jù)庫(kù)數(shù)據(jù)的一致性,鎖就是其中的一種機(jī)制。我們可以用商場(chǎng)的試衣間來(lái)做個(gè)比喻,商場(chǎng)

        里得每個(gè)試衣間都可供多個(gè)消費(fèi)者使用,因此可能出現(xiàn)多個(gè)消費(fèi)者同時(shí)試衣服需要使用試衣間,這時(shí)候就產(chǎn)生沖突了,為了避免沖突,試衣間裝了鎖(其實(shí)就是進(jìn)去之后把門(mén)拴住),某一個(gè)試衣服的人在試衣間里把鎖鎖住了,其他顧客就不能再?gòu)耐饷娲蜷_(kāi)了,只能等待里面的顧客,試完衣服,從里面把鎖打開(kāi),外面的人才能進(jìn)去(網(wǎng)上找到的比喻,非常形象)。不過(guò)我想要是并發(fā)了就尷尬了,哈哈。

        鎖的基本類(lèi)型

          數(shù)據(jù)庫(kù)上的操作可以歸納為兩種:讀和寫(xiě)。
          
          多個(gè)事務(wù)同時(shí)讀取一個(gè)對(duì)象的時(shí)候,是不會(huì)有沖突的。同時(shí)讀和寫(xiě),或者同時(shí)寫(xiě)才會(huì)產(chǎn)生沖突。因此為了提高數(shù)據(jù)庫(kù)的并發(fā)性能,通常會(huì)定義兩種鎖:共享鎖和排它鎖。

        共享鎖(Shared Lock,也叫S鎖)

          共享鎖(S)表示對(duì)數(shù)據(jù)進(jìn)行讀操作。因此多個(gè)事務(wù)可以同時(shí)為一個(gè)對(duì)象加共享鎖。(如果試衣間的門(mén)還沒(méi)被鎖上,顧客都能夠同時(shí)進(jìn)去參觀)
          
          產(chǎn)生共享鎖的sql:select * from ad_plan lock in share mode;

        共享鎖的使用場(chǎng)景

          SELECT … LOCK IN SHARE MODE走的是IS鎖(意向共享鎖),即在符合條件的rows上都加了共享鎖,這樣的話,其他人可以讀取這些記錄,也可以繼續(xù)添加IS鎖,但是無(wú)法修改這些記錄直到你這個(gè)加鎖的過(guò)程執(zhí)行完成(完成的情況有:事務(wù)的提交,事務(wù)的回滾,否則直接鎖等待超時(shí))。
          
          SELECT … LOCK IN SHARE MODE的應(yīng)用場(chǎng)景適合于兩張表存在關(guān)系時(shí)的寫(xiě)操作,拿mysql官方文檔的例子來(lái)說(shuō),一個(gè)表是child表,一個(gè)是parent表,假設(shè)child表的某一列child_id映射到parent表的c_child_id列,那么從業(yè)務(wù)角度講,此時(shí)我直接insert一條child_id=100記錄到child表是存在風(fēng)險(xiǎn)的,因?yàn)閯俰nsert的時(shí)候可能在parent表里刪除了這條c_child_id=100的記錄,那么業(yè)務(wù)數(shù)據(jù)就存在不一致的風(fēng)險(xiǎn)。正確的方法是再插入時(shí)執(zhí)行select * from parent where c_child_id=100 lock in share mode,鎖定了parent表的這條記錄,然后執(zhí)行insert into child(child_id) values (100)就不會(huì)存在這種問(wèn)題了。

        排他鎖(Exclusive Lock,也叫X鎖)

          排他鎖也叫寫(xiě)鎖(X)。

          排他鎖表示對(duì)數(shù)據(jù)進(jìn)行寫(xiě)操作。如果一個(gè)事務(wù)對(duì)對(duì)象加了排他鎖,其他事務(wù)就不能再給它加任何鎖了。(某個(gè)顧客把試衣間從里面反鎖了,其他顧客想要使用這個(gè)試衣間,就只有等待鎖從里面給打開(kāi)了)
        產(chǎn)生排他鎖的sql:select * from ad_plan for update;看到了吧,for update出現(xiàn)了,所以for update 是排他鎖,漲知識(shí)了。

        排他鎖的使用場(chǎng)景

        • 使用場(chǎng)景一:訂單的商品數(shù)量

          但是如果是同一張表的應(yīng)用場(chǎng)景,舉個(gè)例子,電商系統(tǒng)中計(jì)算一種商品的剩余數(shù)量,在產(chǎn)生訂單之前需要確認(rèn)商品數(shù)量>=1,產(chǎn)生訂單之后應(yīng)該將商品數(shù)量減1。

        select amount from product where product_name='XX';update product set amount=amount-1 where product_name='XX';

        顯然1的做法是是有問(wèn)題,因?yàn)槿绻?查詢(xún)出amount為1,但是這時(shí)正好其他session也買(mǎi)了該商品并產(chǎn)生了訂單,那么amount就變成了0,那么這時(shí)第二步再執(zhí)行就有問(wèn)題。那么采用lock in share mode可行嗎,也是不合理的,因?yàn)閮蓚€(gè)session同時(shí)鎖定該行記錄時(shí),這時(shí)兩個(gè)session再u(mài)pdate時(shí)必然會(huì)產(chǎn)生死鎖導(dǎo)致事務(wù)回滾。以下是操作范例(按時(shí)間順序)

        • 使用場(chǎng)景二:數(shù)據(jù)表的狀態(tài)

          如果存在一張表記錄一個(gè)商品的狀態(tài),在訂單的變化過(guò)程中,訂單的狀態(tài)是不斷變化的,而且變化的過(guò)程中肯定也會(huì)有并發(fā)的問(wèn)題,而且很多時(shí)候與其他系統(tǒng)有交互,會(huì)存在補(bǔ)償?shù)那闆r,所以并發(fā)的可能性很大,補(bǔ)償或者為了增加狀態(tài)修改的成功可能性,2次改變狀態(tài)的情況也有,樓主就遇到了這種情況,真操蛋。于是看到有這樣的for update寫(xiě)法。

        update order set status = 1 where product_id = '1';insert order_flow  (..............) value (.........)

        這樣的情況下就有可能訂單的狀態(tài)已經(jīng)更新完成了,但是補(bǔ)償這些額外的消息把狀態(tài)又更新為待處理或者插入了多條流水的情況(多條流水的可能性大,狀態(tài)的那種可能補(bǔ)償滯后)。這個(gè)時(shí)候就可以使用select …. from order where order_id = ‘1’ for update,先鎖住要修改狀態(tài)的表,這樣就不會(huì)別人操作了,自己先后面把流水插入,然后更新?tīng)顟B(tài),完美。但是加了鎖之后性能就很慢了,擔(dān)心性能影響,而且有可能存在死鎖的情況,后面我就修改為流水表中增加一個(gè)唯一索引,這樣插入流水報(bào)錯(cuò)就是已經(jīng)處理過(guò)的記錄了。這樣就不會(huì)存在性能問(wèn)題。

          通過(guò)對(duì)比,lock in share mode適用于兩張表存在業(yè)務(wù)關(guān)系時(shí)的一致性要求,for update適用于操作同一張表時(shí)的一致性要求。

        瀏覽 40
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            亚洲家庭乱伦 | 蜜桃久久99精品久久久酒店 | 《诱人的乳》电影 | 天天色天天射天天操 | 一区二区高清视频 | 国产精品a国产精品a手机版 | 最新国产三级 | 北条麻妃绝顶高潮90分钟 | 91精品乱码久久蜜桃麻豆 | 99精品国产99久久久久久白柏 |