共用鎖和排它鎖 InnoDB實現了標準的行級鎖,包括兩種類型:共用鎖(S)和排它鎖(X) 一個共用鎖(S)允許事務持有這種鎖來讀取一行 一個排它鎖(X)允許事務持有這種鎖來修改或刪除一行 如果事務T1對行r持有一個共用鎖(S),那麼來自其它事務T的對於行r的鎖的請求處理如下: 如果T2請求的是共用鎖 ...
共用鎖和排它鎖
InnoDB實現了標準的行級鎖,包括兩種類型:共用鎖(S)和排它鎖(X)
- 一個共用鎖(S)允許事務持有這種鎖來讀取一行
- 一個排它鎖(X)允許事務持有這種鎖來修改或刪除一行
如果事務T1對行r持有一個共用鎖(S),那麼來自其它事務T的對於行r的鎖的請求處理如下:
- 如果T2請求的是共用鎖(S),那麼將立即被授予共用鎖。這樣的話,T1和T2都持有r的共用鎖(S)
- 如果T2請求的是排它鎖,則不能被立即授予
如果事務T1持有行r的排它鎖,那麼來自其它事務T2對r的任何鎖請求都不能被立即授予。此時,T2必須等待T1釋放對r鎖持有的鎖。
意向鎖
InnoDB支持多種粒度的鎖,它允許行級別的鎖和表級別的鎖共存。為了支持多種粒度級別的鎖,需要用到另外一種鎖,叫意向鎖。在InnoDB中,意向鎖是表級別的鎖,它表示稍後會鎖定表中的一行。有兩種類型的意向鎖:
- 意向共用鎖(IS):事務T打算在表t中的某個行上設置共用鎖(S)
- 共用排它鎖(IX):事務T打算在這些行上設置排它鎖(X)
例如,SELECT ... LOCK IN SHARE MODE將設置一個IS鎖,而SELECT ... FOR UPDATE將設置一個IX鎖
意向鎖協議如下:
- 一個事務在獲得表t上的某一行的共用鎖(S)之前,它必須先在表t上獲得意向共用鎖(IS)或者更高級別的鎖
- 一個事務在獲得表t上的某一行的排它鎖(X)之前,它必須現在表t上獲得意向排它鎖(IX)
一個鎖被授予一個事務請求必須保證和已經存在的鎖相容,如果衝突的話將不能被授予。一個事務必須等待知道和它想獲得的鎖衝突的存在的鎖被釋放。
記錄鎖
一個記錄鎖是一種在索引記錄上的鎖。例如,SELECT c1 FROM t WHERE c1 = 10 FOR UPDATE;阻止其它事務對t.c1=10的行的添加修改刪除操作。
記錄鎖總是鎖定索引記錄,即使表沒有定義索引。對這種情況,InnoDB會創建隱藏的索引,並且用這個索引來加鎖。
間隙鎖
一個間隙鎖是加在索引記錄之間的間隙的鎖,或者在第一個索引記錄之前或者在最後一個索引記錄之後的鎖。例如,SELECT c1 FROM t WHERE c1 BETWEEN 10 AND 20 FOR UPDATE;阻止其它事務插入一個值15在t.c1列上,因為在這個範圍內的所有存在的值的間隙之間已經被鎖定。
一個間隙可能跨過一個單個的索引值,也可能跨過是多個索引值,甚至是空。
間隙鎖是在性能和一致性上的一個折中的方式,它被用在某些事物隔離級別上。
Next-Key鎖
一個next-key鎖是一個在索引記錄上的記錄鎖和一個在索引記錄之前的間隙的間隙鎖的一個結合。
InnoDB允許行級別的鎖以這樣的方式,當它搜索或者掃描一個表的索引時,會給它掃描到的索引記錄設置共用或排它鎖。因此,行級別的鎖實際上是索引記錄鎖,一個next-key鎖是一個索引記錄鎖加上一個在索引記錄之前的間隙的間隙鎖。如果一個會話持有一個索引記錄R的共用或者排它鎖,那麼另外一個會話不能在這個記錄R之前插入新的索引值。
假設一個索引包含的值有:10、11、13、20,那麼對這個索引的next-key鎖會包含下麵這樣幾個間隔,也就是說鎖定範圍覆蓋這些區間:
這是前開後閉區間
預設情況下,InnoDB的預設隔離級別是REPEATABLE_READ。在這種情況下,對於檢索和索引掃描,InnoDB使用next-key鎖。
總結:
1、記錄鎖是索引記錄上的鎖
2、間隙鎖是索引記錄之間的間隙的鎖
3、next-key鎖是記錄鎖加上間隙鎖
4、行級別鎖實際上是記錄鎖
5、意向鎖是表級別的鎖
參考 https://dev.mysql.com/doc/refman/5.7/en/innodb-locking.html