InnoDB 鎖

鎖是InnoDB保障事務隔離性的重要手段,各個存儲引擎以及DB的鎖的實現是不同的。

  • MySql中,MyISAM採用表鎖,InnoDB基於行鎖。
  • Sql Server 2005支持樂觀鎖和悲觀鎖併發;
  • InnoDB提供一致性的非鎖定讀和行級鎖,類似Oracle;

Lock和Latch

latch爲輕量級鎖,稱爲閂鎖,latch類似Java的synchronize,但是Lock更宏觀,latch可以認爲是程序性控制,控制程序邏輯,但是lock是對數據的保護。

Lock Latch
對象 事務
保護 數據庫內容
持續時間 整個事務過程
模式 行鎖、表鎖、意向鎖
死鎖處理 通過wait-for graph、time out等進制進行處理
存在位置 Lock Manager的哈希表中

InnoDB的鎖

InnoDB實現了兩個標準鎖,這兩個鎖是基於行設計的。

  • 共享鎖:S Lock,允許對row數據共享的read;
  • 排他鎖:X Lock,允許對row數據update、delete,但是是獨佔的;

意向鎖:InnoDB實現的一種特殊的表鎖,揭示接下來將要獲取的鎖的類型,意向鎖分爲以下兩類:

  • IX:意向排他鎖;
  • IS:意向共享鎖;
  • 意向鎖不會阻塞除全表掃描以外的任何請求;

鎖相關Sql

#查看引擎狀態查看鎖
show engine innodb status;

#查看處理過程
show full processlist;

# 查詢schema數據庫
select * from information_schema.INNODB_TRX \G

一致性非鎖定讀

InnoDB的讀策略是:在讀取數據的時候不加鎖,也不需要等待X鎖的釋放即可讀取數據,這時讀取的是數據的快照版本。每個數據,由於併發的事務不同,可能存在多個快照數據,這就是多版本快照。

InnoDB使用多版本快照併發控制技術 - MVVC技術控制讀取數據的快照版本。
MVVC技術也是InnoDB實現非鎖定讀的關鍵技術。

事務不同隔離級別的快照版本確定方式不一樣。InnoDB盡在下面兩個級別下使用非鎖定讀技術,其數據快照版本確定方式如下:

  • read commited:讀已提交級別,讀取最新的一個快照版本;
  • repeatable read:可重複讀級別,讀取事務開始時的快照版本;

MVVC技術中確定數據快照版本的時候通過事務號,所以事務號是以關鍵!

顯示加鎖Sql

InnoDB支持顯示加鎖語句,通過在Select的時候加入關鍵語句可以加X和S鎖。這些語句是InnoDB特有的,不是Sql標準。

#Select語句的支持:
# 加X鎖;
select ... for update;

# 加S鎖;
select ... lock in share mode;

自增長字段和鎖

InnoDB實現自增長算法有兩種模式,一種輕量級互斥量,一種是表鎖,MyISAM則採用全表鎖。

InnoDB中自增長的列必須是索引的第一列,也必須是索引。

外鍵和鎖

InnoDB自動爲外鍵添加索引,這可以避免表鎖。如果有外鍵,InnoDB在Insert的時候會去check父表數據,這是會有一個父表的隱式的select操作,這種select不採用一致性非鎖定讀,而且採用Select id from parent_table in lock share model,即主動加S鎖。所以外鍵固然可以保證數據完整性,但是同樣有性能隱患。

鎖算法

InnoDB有3種行鎖算法:

  • Record Lock:單個行上鎖;
  • Grap Lock:間隙鎖,鎖定一個範圍,但是不鎖定本身,鎖定範圍爲開區間;
  • Next-Key Lock:鎖定範圍包括本身,鎖定範圍爲閉區間;

這三種鎖在不同的事務隔離級別下別使用。如InnoDB通過Nex-Key Lock算法鎖定一個範圍數據,這樣可以避免幻讀。

如果字段是唯一索引,則Next-Key Lock有可能降級爲Record Lock;

鎖帶來的問題

鎖可以很好的支持數據庫事務,保證事務的隔離性,但是鎖的不正確使用也會帶來一些問題。在事務的隔離級別中,各個隔離級別都會有一定的問題,這就是鎖帶來的。

  • 在read-ncommitted級別下,因爲沒有使用鎖,所以會發生髒讀問題;
  • 在read committed級別下,因爲使用Record Lock策略,但是沒有對範圍加鎖,所以會有幻讀和不可重複讀問題;
  • 在repeatable read級別下,因爲使用的是Next-Key Lock策略,所以可以消除髒讀和幻讀,但是是否有效率問題呢?

Next-Key Lock :InnoDB解決幻讀策略

幻讀簡單描述是一個事務兩次讀取時讀取到了不同的行數,幻讀和不可重複讀的區別在於,不可重複讀是兩次讀取同一個數據行,數據行內容發生了update,但是幻讀多發生在insert和delete中。

InnoDB使用Next-Key Lock算法作爲Repeatable Read的加鎖策略,這種方式鎖定一個範圍,保證事務隔離性。Read Commited 使用Record Lock作爲加鎖策略,無法保證事務隔離性。

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