mysql8鎖調研(實測)

這裏只說innodb,why?因爲MyISAM基本不用;爲什麼寫這篇文檔?因爲昨天生產出了個事故:有張表,竟然無法select了??也不能看錶結構了??,其他表正常;調研了一天,得出的結論是隻有lock tables … write 才能造成,其他人無法select,但是工程中是沒有這樣的的語句的,最終原因還是沒有找到。。。

一 鎖分層

在這裏插入圖片描述

二 innodb層鎖分類

1. 行級鎖

  • S 共享鎖 :允許獲取到此鎖的事務讀取行
  • X 排他鎖 :允許獲取到此鎖的事務update,delete行

2. 表級鎖-意向鎖

  • IS 意向共享鎖:事務打算對錶中的行設置共享S鎖
  • IX 意向排他鎖:事務打算對錶中的行設置排他X鎖

意向鎖定協議如下

  • 事務在獲得表中某行上的共享鎖之前,必須先獲得表上的IS鎖或更高級別的鎖。
  • 在事務可以獲得表中某一行上的排他鎖之前,它必須首先獲得表上的IX鎖。

sql加了什麼鎖?(以下都是自己的測試和猜測,如有不對請留言指正)

  1. select … for share ,會設置IS鎖,選擇的行的S鎖,如果沒有數據,則只會加表的IS鎖,還有表的S鎖
  2. select … for update,delete,update 會設置IX鎖,選擇的行的X鎖,如果沒有數據,則只會加表的IX鎖,還有表的S鎖
  3. 普通select僅僅需要獲取到表的S鎖
  4. lock tables … write 需要獲取到表的X鎖,和IX鎖
  5. lock tables … read 需要獲取到表的S表,和IS鎖

表級鎖表級鎖表級鎖(重要的事說三遍) 類型兼容性如下
在這裏插入圖片描述
可以通過以下方式來驗證,比如表aa,需要開啓set AUTOCOMMIT = FALSE;
X: lock tables aa write;
S: lock tables aa read;
IX:select * from aa where 1=2 for update;
IS:select * from aa where 1=2 lock in share mode;

3.行鎖

4. 間隙鎖

間隙鎖:指對索引記錄之間間隙的鎖,或者對第一個索引記錄之前或最後一個索引記錄之後的間隙的鎖。例如,SELECT c1 FROM t WHERE c1 BETWEEN 10 and 20 FOR UPDATE;防止其他事務在列t中插入值15,無論列中是否已經有這樣的值,因爲範圍內所有現有值之間的間隙都被鎖定。

5.next-key

next-key鎖是索引記錄上的記錄鎖和索引記錄前間隙上的間隙鎖的組合。
InnoDB執行行級鎖的方式是,當它搜索或掃描一個表索引時,它會對遇到的索引記錄設置共享鎖或排他鎖。因此,行級鎖實際上是索引記錄鎖。索引記錄上的next-key鎖還會影響該索引記錄之前的“間隙”。也就是說,next-key鎖是索引記錄鎖加上索引記錄之前的間隙鎖。如果一個會話對索引中的記錄R有共享或排他鎖,則另一個會話不能在索引順序中緊靠R之前的間隙插入新的索引記錄。
默認情況下,InnoDB操作在可重複讀事務隔離級別。在這種情況下,InnoDB使用next-key鎖來進行搜索和索引掃描,這可以防止幻像行

6.插入意圖鎖

插入意圖鎖是一種間隙鎖,由插入操作設置。如果多個插入到同一個索引間隙的事務沒有在間隙內的相同位置插入,則該鎖將以這樣的方式表示插入的意圖:多個插入到同一個索引間隙的事務不需要相互等待。假設有值爲4和7的索引記錄。分別嘗試插入值爲5和6的獨立事務,在獲得插入行的排他鎖之前,都使用插入意圖鎖鎖住4和7之間的間隙,但不會相互阻塞,因爲這兩行不衝突。

7.AUTO-INC鎖

AUTO-INC鎖是一種特殊的表級鎖,通過事務插入到具有AUTO_INCREMENT列的表中來實現。在最簡單的情況下,如果一個事務向表中插入值,那麼任何其他事務都必須等待對該表進行自己的插入,以便由第一個事務插入的行接收到連續的主鍵值。
innodb_autoinc_lock_mode配置選項控制用於自動增量鎖定的算法。它允許您選擇如何在自動遞增值的可預測序列和插入操作的最大併發性之間進行權衡。

8.空間索引的謂詞鎖

InnoDB支持對包含空間列的列進行空間索引(參見11.4.9節“優化空間分析”)。
爲了處理涉及空間索引的操作的鎖,next-key鎖在支持可重複讀取或可序列化事務隔離級別時不能很好地工作。在多維數據中沒有絕對的排序概念,因此不清楚哪一個是“下一個”鍵。
爲了支持具有空間索引的表的隔離級別,InnoDB使用謂詞鎖。空間索引包含最小邊界矩形(MBR)值,因此InnoDB通過對用於查詢的MBR值設置謂詞鎖來強制對索引進行一致讀取。其他事務不能插入或修改與查詢條件匹配的行。

9.其他注意點

1.lock table命令會獲取兩個鎖,一個mysql層的(S或X),一個是innode層的(IS或IX)
2.所有innodb的鎖在事務提交後,都會釋放,所以在autocommit=1時,使用lock table沒有什麼意義
3.執行普通select,delete,update等操作必須要先獲取到表級別的S鎖,所以只有執行了lock tables aa write後,纔會造成select * from aa因爲鎖阻塞,其他情況select一定不會
4.執行update,delete,掃描 到的行都會加X鎖,所以更新刪除的時候一定要用唯一索引,否則無關的行將會被鎖定,即使其他where條件會把這條數據過濾掉

三參考資料

https://dev.mysql.com/doc/refman/8.0/en/innodb-locking.html

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