行鎖的三種算法

1、Record Lock:單個記錄上的鎖

   Record Lock老是會鎖住索引記錄,若是InnoDB存儲引擎表在創建的時候沒有設置任何一個索引,那麼這時InnoDB存儲引擎會使用隱式的主鍵來進行鎖定。算法

、Gap Lock:間隙鎖

   設計目的:是爲了解決Phantom Problem(幻象/幻讀),利用這種鎖技術,鎖定的不是單個值,而是一個範圍。markdown

3、Next-Key Lock:Gap Lock+Record Lock

   Next-Key Lock是結合了Gap Lock和Record Lock的一種鎖定算法,在此種算法下,InnoDB對於行的查詢都是採用這種鎖定算法。併發

  例如:優化

    有十、十一、1三、20這四個值,那麼索引可能被Next-Key Locking的區間爲:spa

    一、(-∞,10]設計

    二、(10,11]code

    三、(11,13]orm

    四、(13,20]索引

    五、(20,+∞)事務

  除了Next-Key Locking,還有Previous-Key Locking,如上面的例子,可鎖定的區間爲:

    一、(-∞,10)

    二、  [10,11)

    三、  [11,13)

    四、  [13,20)

    五、  [20,+∞)

  然而,當查詢的索引含有惟一屬性時,InnoDB存儲引擎對Next-Key Lock進行優化,將其降級爲Record Lock,即僅鎖住索引自己,而不是範圍。如表中有1,2,5的id數據:

  

  會話A首先對a=5進行X鎖。而因爲a是主鍵且惟一,所以鎖定的僅是5這個值,而不是(2,5)的範圍,這樣在B中插入值4不會阻塞,能夠當即插入並返回。即鎖定由Next-Key Lock算法降級爲Record Lock,從而提升了併發性。

   Next-Key Lock降級爲Record Lock僅在查詢的列惟一索引的狀況下。

  如果輔助索引,則狀況會徹底不一樣如:

  CREATE TABLE z(a INT,b INT,PRIMARY KEY(a),KEY(b))

  INSERT INTO z SELECT 1,1;

  INSERT INTO z SELECT 3,1;

  INSERT INTO z SELECT 5,3;

  INSERT INTO z SELECT 7,6;

  INSERT INTO z SELECT 10,8;

  表z的b列是輔助索引,若在會話A中執行下面的SQL:

  SELECT * FROM z WHERE b=3 FOR UPDATE;

  這是Sql語句經過索引列b進行查詢,所以其使用傳統的Next-Key Locking加鎖,而且因爲兩個索引,其須要分別進行鎖定。對於彙集索引,其僅對a等於5的索引加上record Lock對於輔助索引,其加上的是Next-Key Lock,鎖定的範圍是(1,3),須要注意的是,InnoDB存儲引擎還會對輔助索引下一個鍵值加上gap lock,即還有一個輔助索引的範圍爲(1,6)的鎖,所以,在B會話中運行下面的Sql語句,都會被阻塞:

  SELECT * FORM z WHERE a=5 LOCK IN SHARE MODE;

  INSERT INTO z SELECT 4,2;

  INSERT INTO z SELECT 6,5;

  而執行下面的語句,不會阻塞:

  INSERT INTO z SELECT 8,6;

  INSERT INTO z SELECT 2,0;

  INSERT INTO z SELECT 6,7;

 

  在默認的事務隔離級別下,即REPEATABLE READ下,InnoDB存儲引擎採用Next-Key Locking機制來避免Phantom Problem(幻象問題)

相關文章
相關標籤/搜索