<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如何加鎖控制并發(fā)

          共 2562字,需瀏覽 6分鐘

           ·

          2021-02-02 09:24

          點擊上方藍色字體,選擇“標星公眾號”

          優(yōu)質(zhì)文章,第一時間送達

          ? 作者?|? 雪山飛豬

          來源 |? urlify.cn/NnqYNb

          76套java從入門到精通實戰(zhàn)課程分享

          前言

          鎖總體可以分為樂觀鎖和悲觀鎖,簡單說,樂觀鎖用版本號控制,悲觀鎖用鎖控制。

          下面是待會要用來測試的數(shù)據(jù)

          #?添加一個user表
          CREATE?TABLE?`users`?(
          ??`id`?int(11)?NOT?NULL?AUTO_INCREMENT?COMMENT?'ID',
          ??`name`?varchar(255)?NOT?NULL?COMMENT?'姓名',
          ??PRIMARY?KEY?(`id`)
          )?ENGINE=InnoDB?AUTO_INCREMENT=2?DEFAULT?CHARSET=utf8;
          #?插入3條數(shù)據(jù)
          INSERT?INTO?`users`?(`id`,?`name`)
          VALUES
          ?(1,?'雪山飛豬'),
          ?(2,?'chenqionghe'),
          ?(3,?'cqh');

          查詢結(jié)果如下:

          一、樂觀鎖

          核心原理是增加一個version的字段來控制。
          舉個場景,我們希望并發(fā)更新單行記錄的時候的時候,只有一個進程更新成功,如下

          UPDATE?users?SET?name="雪山飛豬"?WHERE?id=3
          UPDATE?users?SET?name="chenqionghe"?WHERE?id=3

          上面這兩個sql最終都會更新成功,且以最后更新結(jié)果為主。

          解決辦法是添加一個version字段

          添加version字段

          ALTER?TABLE?users?ADD?`version`?INT?NOT?NULL?DEFAULT?'0'

          解決辦法是添加一個version字段,每個更新時where條件都加上它,并且也更新它

          UPDATE?users?SET?name="雪山飛豬",version=version+1?WHERE?id=3?AND?version=0
          UPDATE?users?SET?name="chenqionghe",version=version+1?WHERE?id=3?AND?version=0

          這次變成了只會更新成功一次,誰先搶到這條記錄以誰為主,因為當前一個進程更新成功后版本號已經(jīng)變化了,第二個進程找不到這條記錄了。
          這就是最簡單的CAS機制。

          二、悲觀鎖

          其實類似Go語言里的Mutex和RwMutex,可以參考這篇文章:Go語言中的互斥鎖和讀寫鎖(Mutex和RWMutex)

          讀鎖

          也叫共享鎖或S鎖,當給數(shù)據(jù)表加上共享鎖的時候,表就變成了只讀模式。
          我們可以鎖全表,也可以鎖全表或部分行,如下

          全表鎖(LOCK TABLE 表 READ)

          語法如下

          LOCK?TABLE?表?READ
          UNLOCK?TABLE;

          我們來測試一個,第一個進程執(zhí)行

          LOCK?TABLE?users?READ;

          第二個進程執(zhí)行正常讀

          SELECT?*?FROM?users?WHERE?id=1;


          可以正常查詢。我們再來執(zhí)行一下更新

          UPDATE?users?SET?name="chenqionghe"?WHERE?id=1


          出現(xiàn)了等待。

          我們給第一個進程解鎖

          再看第二個進程,已經(jīng)更新成功

          行鎖(SELECT ... LOCK IN SHARE MODE)

          BEGIN;
          SELECT?*?FROM?users?WHERE?id?IN?(1,2)?LOCK?IN?SHARE?MODE
          COMMIT;

          必須配合事務使用,BEIN開始后,鎖定的行,外部只能查詢,不能更新

          我們來測試一下,第一個進程執(zhí)行

          BEGIN;
          SELECT?*?FROM?users?WHERE?id?IN?(1,2)?LOCK?IN?SHARE?MODE

          注意:這時候事務沒提交


          這里鎖定了id為1和2的記錄行。我們第二個進程執(zhí)行更新

          UPDATE?users?SET?name="雪山飛豬"?WHERE?id=1


          又一次出現(xiàn)了等待。
          好,這時候我們將第一個進程的事務提交

          COMMIT;


          第二個進程更新成功了,如下

          寫鎖

          也排他鎖、獨占鎖,理解成讀和寫都不行了,語法如下

          全表鎖(LOCK TABLE 表 WRITE)

          LOCK?TABLE?表?WRITE
          UNLOCK?TABLE;

          我們來測試一下,第一個進程執(zhí)行

          LOCK?TABLE?users?WRITE;


          這時候已經(jīng)鎖定全表,我們再用另一個進程查詢一下id為1的數(shù)據(jù)

          SELECT?*?FROM?users?WHERE?id=1


          可以看到,查詢已經(jīng)發(fā)生了等待。
          我們再將第一個進程解鎖

          UNLOCK?TABLE


          這時候,第二個進程立馬查詢成功

          行鎖(SELECT ... FOR UPDATE)

          當我們對數(shù)據(jù)進行更新的時候(INSERT、DELETE、UPDATE)的時候,數(shù)據(jù)庫會自動使用排它鎖,防止其他事務操作該數(shù)據(jù)

          BEGIN;
          SELECT?*?FROM?users?WHERE?id?IN?(1,2)?LOCK?IN?SHARE?MODE
          COMMIT;

          我們再來測試一下,第一個進程鎖定id為1和2的記錄

          BEGIN;
          SELECT?*?FROM?users?WHERE?id?IN?(1,2)?FOR?UPDATE

          注意:這時候事務沒提交

          我們先用第二個進程來更新id為3的記錄(未被鎖定)

          UPDATE?users?SET?name="chenqionghe"?WHERE?id=3


          執(zhí)行成功了。
          我們再來更新一個id為1的記錄

          UPDATE?users?SET?name="chenqionghe"?WHERE?id=1

          發(fā)生了等待,說明已經(jīng)被鎖定了。
          好,我們提交第一個進程的事務

          COMMIT;

          再去看第二個進程,已經(jīng)更新成功

          簡單說樂觀鎖用version控制,悲觀鎖的表鎖一般用不著,行的讀鎖用LOCK IN SHARE MODE,寫鎖用FRO UPDATE,就是這么簡單!





          粉絲福利:Java從入門到入土學習路線圖

          ??????

          ??長按上方微信二維碼?2 秒


          感謝點贊支持下哈?

          瀏覽 38
          點贊
          評論
          收藏
          分享

          手機掃一掃分享

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

          手機掃一掃分享

          分享
          舉報
          <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>
                  久日视频 | 成人H精品动漫在线无码播放 | 成人AV一区二区三区四区 | 玖玖精品热在线 | 大香蕉国产强奸在线 |