select * from t where c=5 for update 排它鎖

  • RC隔離級別下,
    • 對非索引字段更新,有個鎖全表記錄的過程,
      • 不符合條件的會及時釋放行鎖,沒必要等事務結束時釋放;
      • RC沒有間隙鎖的概念
    • 而直接用索引列更新,只會鎖索引查找值和行。
      • update產生的X鎖在不釋放的狀況下,
        • DELETE語句沒法執行,
        • 是UPDATE語句能更新不符合以前X鎖的記錄。
  • RR隔離級別下,爲保證binlog記錄順序
    • 非索引更新會鎖住全表記錄,
    • 且事務結束前不會對不符合條件記錄有逐步釋放的過程。
    • DELETE和UPDATE語句都不能執行

版本5.7.13
rc模式下:
session 1:
begin;
select * from t where c=5 for update; 
session 2:
delete from t where c=10 --等待
session 3:
insert into t values(100001,8) --成功session

session 4 : update t set c=100 where id=10  -- 成功
session 1:
commit
session 2:事務執行成功
rr模式下:
begin;
select * from t where c=5 for update; 
session 2:
delete from t where c=10 --等待
session 3:
insert into t values(100001,8) --等待spa

session 4 : update t set c=100 where id=10 --等待
session 1:
commit
session 2:事務執行成功
session 3:事務執行成功
從上面這兩個簡單的例子,能夠大概看出上鎖的流程.
無論是rr模式仍是rc模式,這條語句都會先在server層對錶加上MDL S鎖,而後進入到引擎層。

rc模式下,因爲數據量不大隻有10W。經過實驗能夠證實session 1上來就把該表的全部行都鎖住了。
致使其餘事務要對該表的全部現有記錄作更新,是阻塞狀態。爲何insert又能成功?
說明rc模式下for update語句沒有上gap鎖,因此不阻塞insert對範圍加插入意向鎖,因此更新成功。
session 1commit後,session 2執行成功。代表全部行的x鎖是在事務提交完成之後才釋放。

rr模式下,session 1和session 2與rc模式下都同樣,說明rr模式下也對全部行上了X鎖。
惟一的區別是insert也等待了,是由於rr模式下對沒有索引的更新,聚簇索引上的全部記錄,都被加上了X鎖。其次,聚簇索引每條記錄間的間隙(GAP),也同時被加上了GAP鎖。因爲gap鎖阻塞了insert要加的插入意向鎖,致使insert也處於等待狀態。只有當session 1 commit完成之後。session 1上的全部鎖纔會釋放,S2,S3執行成功

因爲例子中的數據量還比較小,若是數據量達到千萬級別,就比較直觀的能看出,上鎖是逐行上鎖的一個過程.掃描一條上一條,直到全部行掃描完,rc模式下對全部行上x鎖。rr模式下不只對全部行上X鎖,還對全部區間上gap鎖.直到事務提交或者回滾完成後,上的鎖纔會被釋放。server

相關文章
相關標籤/搜索