行鎖:InnoDB替代MyISAM的重要原因

InnoDB能夠替代MyISAM的原因有二:

  • InnoDB支持事務:適合在併發條件下要求數據一致的場景
  • InnoDB支持行鎖:有效降低由於刪除或者更新導致的鎖定

1. 兩階段鎖

傳統的關係型數據庫加鎖的一個原則是:兩階段鎖原則。
兩階段鎖:鎖操作分爲兩個階段,加鎖階段和解鎖階段,並且保證加鎖階段和解鎖階段不相交。
我們可以通過下面這張表理解兩階段鎖:
在這裏插入圖片描述

2. InnoDB行鎖模式

InnoDB實現了以下兩種類型的行鎖:

  • 共享鎖:允許一個事務去讀一行,阻止其他事務獲得相同數據集的排它鎖
  • 排它鎖:允許獲得排它鎖的事務更新數據,阻止其他事務取得相同數據集的共享讀鎖和排它寫鎖

對於普通select語句,InnoDB不會加任何鎖,事務可以通過以下語句顯式給記錄集加共享鎖或排它鎖:

  • 共享鎖:select * from table where … lock in share mode
  • 排它鎖:select * from table where … for update

3. InnoDB行鎖算法

InnoDB行鎖的三種算法:

  • Record Lock:單個記錄上的索引加鎖
  • Gap Lock:間隙鎖,對索引項之間的間隙加鎖,但不包括記錄本身
  • Next-Key Lock: Gap Lock + Record Lock, 鎖定一個範圍,並且鎖定記錄本身
    InnoDB行鎖實現特點意味着:如果不通過索引條件檢索數據,那麼InnoDB將對錶中所有記錄加鎖,實際效果跟表鎖一樣

4. 事務隔離級別

不同事務隔離級別對應的行鎖也是不一樣的,MySQL有4中事務隔離級別:

  • 讀未提交:所有事務都可以看到其他未提交事務的執行結果,可能會出現髒讀
  • 讀已提交:一個事務只能看見已提交事務所做的改變。因爲同一事務的其他實例在該實例處理期間可能會有新的提交,所以可能會出現幻讀
  • 可重複讀:MySQL的默認隔離級別,確保同一事務的多個實例在併發讀取數據時,會看到同樣的數據行。消除了髒讀、不可重複讀,可能會出現幻讀
  • 串行:最高的隔離級別,通過強制事務排序,使之不可能出現幻讀

髒讀:讀取到未提交的數據
幻讀:一個事務按照相同的查詢條件重新讀取以前檢索過的數據,卻發現其他事務插入了滿足其查詢條件的數據或者發現以前檢索過的數據發生了修改

5. 讀已提交隔離級別下的行鎖

  • 沒有索引的情況下,InnoDB的當前讀(select … for update)會對所有記錄都加鎖
  • 在查詢條件有索引的情況下,那麼SQL需要在滿足條件的索引上加鎖,並且會在他們對應的聚簇索引上加鎖
  • 在更新數據時,如果條件字段沒索引,則表中所有記錄都會被加上排它鎖,所以儘量讓查詢走索引

6.可重複讀隔離級別下的行鎖

  • 條件字段非索引的當前讀不但會把每條記錄都機上排它鎖,還會把每個間隙加上間隙鎖
  • 唯一索引爲條件的當前讀不會有間隙鎖,因爲根據唯一索引查詢最多就一條記錄,而且相同索引記錄的值,一定不會再新增
  • 可重複讀通過間隙鎖解決了幻讀
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章