<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Mysql的排他鎖和共享鎖

          共 2508字,需瀏覽 6分鐘

           ·

          2020-12-05 21:19

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

          鎖的基本概念

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

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

          鎖的基本類型

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

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

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

          共享鎖的使用場景

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

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

            排他鎖也叫寫鎖(X)。

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

          排他鎖的使用場景

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

            但是如果是同一張表的應(yīng)用場景,舉個例子,電商系統(tǒng)中計算一種商品的剩余數(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的做法是是有問題,因為如果1查詢出amount為1,但是這時正好其他session也買了該商品并產(chǎn)生了訂單,那么amount就變成了0,那么這時第二步再執(zhí)行就有問題。那么采用lock in share mode可行嗎,也是不合理的,因為兩個session同時鎖定該行記錄時,這時兩個session再update時必然會產(chǎn)生死鎖導(dǎo)致事務(wù)回滾。以下是操作范例(按時間順序)

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

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

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

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

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

          瀏覽 40
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          評論
          圖片
          表情
          推薦
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

          分享
          舉報
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  青娱乐偷拍视频99 | 欧美三级片在线看 | 成人免费性生活视频 | 最新的成人豆花AV | 亚欧成人精品无码视频在线观看 |