Innodb鎖

鎖的分類

  • Innodb的鎖分爲兩種:1、輕量級的閂鎖(latch),保護內存中的數據結構;2、鎖(lock),保護數據,一般僅在commit或rollback後釋放。
    190823.latch.png
  • lock的分類,SS兼容,其餘互斥:
    • 共享鎖(S Lock),允許事務讀一行記錄。
    • 排它鎖(X Lock),允許事務刪除或更新一條記錄。
  • 意向鎖:表級鎖,事務希望在更細粒度上加鎖。由於Innodb支持的是行級鎖,意向鎖不會阻塞除全表掃描之外的請求。
    • 意向共享鎖:事務希望獲得某幾行的共享鎖。
    • 意向排它鎖:事務希望獲得某幾行的排它鎖。
      190823.ISIX.png

讀取加鎖

一致性非鎖定讀

  • 如果讀取的行由於update或delete,加X鎖,不會等鎖釋放,而是讀行的快照(undo段實現)。Innodb快照讀

一致性鎖定讀

  • 對select語句顯示加鎖。
    • 對讀取的行加X鎖:select … for update。
    • 對讀取的行加S鎖:select … lock in share mode。

自增長和鎖

  • 之前使用自增長計數器,是一種特殊的表鎖,完成自增長值插入的sql後生效。
  • 5.1.22之後使用輕量級的互斥量自增長機制。
  • sequence id不使用數據庫自增長,提高插入效率。

外鍵和鎖

  • 外鍵列,如果沒有顯式的加索引,innodb會自動加索引,避免表鎖。
  • 外鍵值插入時:需要查詢父表的記錄,用一致性鎖定讀,加S鎖。
  • 儘量在業務層保證數據的一致性,減小數據的壓力。

加鎖算法

Record Lock

  • 鎖單行上的記錄。
  • RC級別使用。

Gap Lock

  • 間隙鎖,鎖小於記錄值不包括記錄本身的範圍。

Next-Key Lock

  • 範圍包括記錄本身。以上兩個鎖的和。
  • innodb查詢的列是輔助索引上的鍵值,則會對鍵值加Next-key lock,並且對下一個鍵值加Gap Lock。
  • RR級別使用,可解決幻讀問題。

加鎖規則

  • 加鎖規則可以概括爲:兩個原則、兩個優化和一個bug:
    • 原則1:加鎖的基本單位是索引區間,前開後閉
    • 原則2:查找過程中訪問到的對象纔會加鎖
    • 優化1:索引上的等值查詢,給唯一索引加鎖的時,next-key lock退化成行鎖
    • 優化2:索引上的等值查詢,給非唯一索引加鎖時,向右遍歷時且鎖區間最後一個值不滿足等值條件的時候,next-key lock退化爲間隙鎖
    • 1個bug:唯一索引上的範圍查詢會訪問到不滿足條件的第一個值爲止。
  • 參考

例子

Table t (
  a int,
  b int,
  primary key(a),
  key(b)
  • 如果查詢條件無索引,執行select * from t where b = 3 for update,走聚集索引全表掃描,所有記錄加鎖。
  • 表中有兩條索引,(1,1),(3,1),(5,3),(7,6)這幾條記錄。
    • b列輔助索引,加next-key lock,索引分爲幾段加鎖區間:(-∞,1],(1,3],(3,6],(6,+∞)。
  • 執行 select * from t where b = 3 for update,會對兩條索引分別加鎖
    • 輔助索引:加Next-key Lock,並對下一個鍵值加gap lock,鎖定輔助索引b的範圍(1,3]和(3,6)。
    • 聚集索引:由於查詢未使用覆蓋索引,對a=5聚集索引加Record Lock。
  • 執行select * from t where b > 2 for update
    • 輔助索引:鎖住b[2,+∞)。
    • 聚集索引:由於查詢未使用覆蓋索引,加鎖的輔助索引值對應的聚集索引都加鎖。
  • 詳細的加鎖樣例

解鎖算法

  • 事務提交時釋放鎖。
    • 事務1 加X鎖,未提交之前事務2 在改鎖上寫操作阻塞。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章