詳解MySQL行鎖
鎖是計算機協調多個程序或執行緒併發訪問某一資源的機制。鎖保證資料併發訪問的一致性、有效性;鎖衝突也是影響資料庫併發訪問效能的一個重要因素。鎖是Mysql在伺服器層和儲存引擎層的的併發控制。MySQL中從對資料操作的粒度分為表鎖和行鎖。表鎖是指對一整張表加鎖,一般是 DDL 處理時使用;而行鎖則是鎖定某一行或者某幾行,或者行與行之間的間隙。本文我們就重點來介紹MySQL行鎖。
行鎖不同儲存引擎的行鎖實現不同,後續沒有特別說明,則行鎖特指 InnoDB 實現的行鎖。在瞭解 InnoDB 的加鎖原理前,需要對其儲存結構有一定的瞭解。InnoDB 是聚簇索引,也就是 B+樹的葉節點既儲存了主鍵索引也儲存了資料行。而 InnoDB 的二級索引的葉節點儲存的則是主鍵值,所以通過二級索引查詢資料時,還需要拿對應的主鍵去聚簇索引中再次進行查詢。
行鎖的模式有:讀意向鎖,寫意向鎖,讀鎖,寫鎖和自增鎖(auto_inc),下面我們依次來看。
1.讀寫鎖
讀鎖,又稱共享鎖(Share locks,簡稱 S 鎖),加了讀鎖的記錄,所有的事務都可以讀取,但是不能修改,並且可同時有多個事務對記錄加讀鎖。
寫鎖,又稱排他鎖(Exclusive locks,簡稱 X 鎖),或獨佔鎖,對記錄加了排他鎖之後,只有擁有該鎖的事務可以讀取和修改,其他事務都不可以讀取和修改,並且同一時間只能有一個事務加寫鎖。
2.讀寫意向鎖
由於表鎖和行鎖雖然鎖定範圍不同,但是會相互衝突。所以當你要加表鎖時,勢必要先遍歷該表的所有記錄,判斷是否加有排他鎖。這種遍歷檢查的方式顯然是一種低效的方式,MySQL 引入了意向鎖,來檢測表鎖和行鎖的衝突。意向鎖也是表級鎖,也可分為讀意向鎖(IS 鎖)和寫意向鎖(IX 鎖)。當事務要在記錄上加上讀鎖或寫鎖時,要首先在表上加上意向鎖。這樣判斷表中是否有記錄加鎖就很簡單了,只要看下錶上是否有意向鎖就行了。意向鎖之間是不會產生衝突的,也不和 AUTO_INC 表鎖衝突,它只會阻塞表級讀鎖或表級寫鎖,另外,意向鎖也不會和行鎖衝突,行鎖只會和行鎖衝突。
3.自增鎖
AUTOINC 鎖又叫自增鎖(一般簡寫成 AI 鎖),是一種表鎖,當表中有自增列(AUTOINCREMENT)時出現。當插入表中有自增列時,資料庫需要自動生成自增值,它會先為該表加 AUTOINC 表鎖,阻塞其他事務的插入操作,這樣保證生成的自增值肯定是唯一的。AUTOINC 鎖具有如下特點:
1)AUTO_INC 鎖互不相容,也就是說同一張表同時只允許有一個自增鎖;
2)自增值一旦分配了就會 +1,如果事務回滾,自增值也不會減回去,所以自增值可能會出現中斷的情況。
顯然,AUTOINC 表鎖會導致併發插入的效率降低,為了提高插入的併發性,MySQL 從 5.1.22 版本開始,引入了一種可選的輕量級鎖(mutex)機制來代替 AUTOINC 鎖,可以通過引數 innodbautoinclockmode 來靈活控制分配自增值時的併發策略。
行鎖是MySQL資料庫中非常重要的鎖,行鎖根據場景的不同又可以進一步細分,依次為 Next-Key Lock,Gap Lock 間隙鎖,Record Lock 記錄鎖和插入意向 GAP 鎖。不同的鎖鎖定的位置是不同的,比如說記錄鎖只鎖住對應的記錄,而間隙鎖鎖住記錄和記錄之間的間隔,Next-Key Lock 則所屬記錄和記錄之前的間隙。