MySQL——InnoDB存儲引擎的鎖

  鎖是數據庫系統系統區別於文件系統的一個關鍵特性。
參考:https://blog.ouyangsihai.cn/mysql-de-you-yi-shen-qi-suo.html

一、lock和 latch

1. latch

  latch在MySQL中是用來保證併發多線程操作操作臨界資源的鎖,鎖定的對象線程,是和咱們使用的Java等傳統語言中的鎖意義相近,而且沒有死鎖檢測的機制

2. lock

   lock是MySQL中在事務中使用的鎖,鎖定的對象是事務,來鎖定數據庫中表、頁、行;通常只有在事務commit或者rollback後進行釋放。lock是有死鎖機制的,當出現死鎖時,lock有死鎖機制來解決死鎖問題:超時時間(參數innodb_lock_wait_timeout)、wait-for graph。

我們通常講的MySQL的“鎖”,一般就是說的lock。以下就是InnoDB中“鎖”的大分類:
在這裏插入圖片描述

二、lock的種類

MySQL Lock大體上可以分爲:表鎖、行鎖、意向鎖三種。
在這裏插入圖片描述
1.共享/排他鎖


行鎖分爲:S Lock和X Lock。S Lock :讀鎖;X Lock:寫鎖
兩鎖之間的兼容性如下。

       X         S
X     不兼容     不兼容
S     不兼容     兼容

簡單總結爲:讀鎖可以讀、不可寫;寫鎖不可讀、也不可寫。

2.意向鎖


可以參考:https://juejin.im/post/5b85124f5188253010326360
意向鎖是一種不與行級鎖衝突表級鎖,這一點非常重要。意向鎖分爲兩種:

  • 意向共享鎖(intention shared lock, IS):事務有意向對錶中的某些行加共享鎖(S鎖)
  • 事務要獲取某些行的 S 鎖,必須先獲得表的 IS 鎖。
    SELECT column FROM table ... LOCK IN SHARE MODE;
    
  • 意向排他鎖(intention exclusive lock, IX):事務有意向對錶中的某些行加排他鎖(X鎖)
  • 事務要獲取某些行的 X 鎖,必須先獲得表的 IX 鎖。
    SELECT column FROM table ... FOR UPDATE;
    

    即:意向鎖是有數據引擎自己維護的,用戶無法手動操作意向鎖,在爲數據行加共享 / 排他鎖之前,InooDB 會先獲取該數據行所在在數據表的對應意向鎖

    InnoDB支持多粒度的鎖,即:允許表鎖和行鎖同時存在。
    但是,假如表鎖覆蓋了行鎖的數據,所以表鎖和行鎖也會產生衝突。如:

    trx1 BEGI
    trx1 給 T1 加X鎖修改數據。
    
    trx2 BEGIN
    trx2 給 T1 加表鎖修改表結構
    

    表鎖和行鎖之間就產生了衝突,爲了解決這種表鎖和行鎖共存的問題,就產生了意向鎖這個東西。
    意向鎖:從字面意思也很好理解,就是提前表明一個“意向”

    意向鎖僅僅是表明意向,它其實非常弱,意向鎖之間可以相互並行,並不是排斥的。意向鎖之間的兼容性問題:

          IS     IX
    IS   兼容    兼容
    IX   兼容    兼容
    

    於是,上述現象就變爲了:

    trx1 BEGIN
    trx1 給 T1 先加IX ,然後在某一行記錄加X鎖。
    
    trx2 BEGIN
    trx2 給 T1 加表鎖X(事務被阻塞,等待加鎖成功)
    
    trx2 修改表結構
    

    意向鎖存在的意義是什麼呢?

    ”沒有意向鎖,行鎖和表鎖照樣可以共存,試問如何共存?” “查看錶中某一行存在X鎖” “如何查看呢?” 唯有全表掃描…

      意向鎖的存在就是解決了“全表掃描”的性能問題,所以,意向鎖一定是“表級”鎖,告訴整張表XXX行存在X鎖。此時假如進行表操作就會被阻塞。

  • 總結
  • InnoDB 支持多粒度鎖,特定場景下,行級鎖可以與表級鎖共存。
    意向鎖之間互不排斥,但除了 IS 與 S 兼容外,意向鎖會與 共享鎖 /排他鎖 互斥。
    IX,IS是表級鎖,不會和行級的X,S鎖發生衝突只會和表級的X,S發生衝突
    意向鎖在保證併發性的前提下,實現了行鎖和表鎖共存且滿足事務隔離性的要求。

    3.主鍵自增鎖
      自增鎖(auto-inc Locks)是一種特殊的表級鎖,專門針對事務插入AUTO_INCREMENT類型的列,往往就是主鍵列。可以保證主鍵的值自增是“原子操作”,不會出現一致性、唯一性問題。

    4.行鎖的具體分類
    在這裏插入圖片描述
    InnoDB存儲引擎有以上3種行鎖算法。以上3種,都是實現在索引上的。

    ①記錄鎖(Record Lock)
    記錄鎖(Record Lock)總是會去鎖住索引記錄。
    假如沒有任何一個索引,那麼InnoDB會鎖住隱形創建的那個主鍵。

    注意:這裏鎖的是索引,不一定只是主鍵索引哦,還可能是二級普通索引。

    ②間隙鎖(Gap Lock)
    顧名思義,它會封鎖索引記錄中的“縫隙”,防止其他事務在“縫隙”中插入數據。
    它鎖定的是一個不包含索引本身的範圍。

    例如以下索引數據:
    在這裏插入圖片描述
    間隙鎖(Gap Lock)可以鎖的將是以下範圍
    在這裏插入圖片描述

    具體的範圍還要根據查詢條件不同而定。
    間隙鎖開啓的事務隔離級別是 Repeatable Read,如果把數據庫事務級別降爲Read Committed(默認是 Repeatable Read),間隙鎖則會自動失效。

    ③ 臨鍵鎖(Next-Key Lock)
    Next-Key Lock可以說是記錄鎖(Record Lock)和間隙鎖(Gap Lock)的組合,既封鎖了”縫隙”,又封鎖了索引本身

    還是上面的索引數據:
    在這裏插入圖片描述
    臨鍵鎖(Next-Key Lock)鎖住的範圍將是:
    在這裏插入圖片描述

    Next-key Lock在索引具有唯一性的時候,例如主鍵索引的數據,將會降級爲記錄鎖(Read Lock),以增加併發性。
    例如:

            T1                                     T2
            BEGIN;                   |            
       select * From T               |           
       where id = 5 for update       |
    ---------------------------------------------------------------
                                     |            BEGIN; 
                                     |          Insert into t (4, xx);
    ---------------------------------------------------------------              
                                     |          COMMIT
                                     |             
    ----------------------------------------------------------------
         COMMIT                      |                            
                                     |
                                     |
    -----------------------------------------------------------------
    

    以上情況,就會把Next-key Lock降級爲記錄鎖(Read Lock)

    發表評論
    所有評論
    還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
    相關文章