分散式鎖-資料庫實現

2020-10-02 13:00:07

 

1:for update 的原理

select 檢索出的資料, for update 加上了一把鎖,其他的人是不能修改這個資料的,也不能在給這個資料加鎖。其他執行緒可以檢索出來,但是我在用 for update 再給這些資料加鎖是加不上的,因為這個鎖呢,已經被前一個執行緒給鎖住了。其他人是不能給它加鎖的,在加鎖的期間,其他人也不能修改這些資料。因為update 更新資料呢,是要獲取這些資料的鎖的

2:程式碼實現

    @Transactional(rollbackFor = Exception.class)
    @RequestMapping("/database")
    public String databaseLock () throws InterruptedException {
        log.info("進入方法");
        BusinessLock businessLock = businessLockMapper.getLock("demo");
        if (ObjectUtils.isEmpty(businessLock)) {
            log.info("分散式鎖找不到");
        }
        log.info("進入鎖");
        Thread.sleep(6000);
        log.info("方法執行完成");
        return "方法執行完成";
    }

 mapper 裡面的sql

        SELECT * FROM business_lock WHERE  business_code = #{businessCode}  FOR UPDATE
  •  開啟兩個範例,埠分別是  8080  8088
  • 下圖 8080  應用   
  1. 58:16秒      進入方法
  2. 58:16秒      進入鎖
  3. 58:22秒      方法執行完成

 

  • 下圖 8088  應用   
  1. 58:17秒      進入方法
  2. 58:22秒      進入鎖
  3. 58:28秒      方法執行完成

在程式碼中我們讓獲取到鎖的應用休眠6秒 ,8080 和 8088 差不多同一時間進入方法,

但是8080更早一些所有獲得到了鎖,而8088就在資料庫中阻塞,等待獲取鎖。

在16秒 8080獲得鎖等待6秒 22秒釋放鎖,這時  8088才拿到了鎖。說明在多個應用中鎖是有生效的。

教學原始碼+sql:https://apk-1257934361.cos.ap-guangzhou.myqcloud.com/lock/database-lock/database-lock.zip 

3:用native 測for update

  • 先將當前頁面的資料庫自動提交先關掉

為什麼要先關掉呢?你現在檢索出來以後或者for update 加了鎖,加了鎖以後它馬上事務呢就會自動的去提交,事務提交了。鎖就會自動釋放了。其他的對談,還會檢索出這條資料來

  • 下圖:預設是自動提交事務的 

  • 下圖:這時候都是沒有關閉自動提交事務的。兩者都可以執行加鎖頁面。說明沒有起到我們想要的作用
  • 下圖:關閉兩個視窗的自動提交事務
  •  再次檢索帶有  for update 關鍵字的sql 。這時候鎖被左視窗鎖住了,導致右視窗無法加鎖。這時候在  左視窗執行commit 提交事務操作,右視窗立馬就查詢出資料了 。說明鎖是生效的

  • 左視窗執行 for update ,右視窗不使用  for update 而是直接執行查詢 是可以查詢出資料的 

4:總結