《專題三分散式系統》之《第四章 資料儲存層優化(上)-資料庫優化》之 《第五節 詳解資料庫鎖》

qq_23204557發表於2020-12-16

《4.5.1-MVCC多版本併發控制》

InnoDB MVCC的實現基於Undo log?

《4.5.2.1-資料庫-行級鎖》

  • 讀鎖與寫鎖

行共享鎖、 排他鎖(X鎖,寫鎖,獨佔鎖)
資料行被事務新增 S 鎖後,其他事務可以新增 S 鎖,但是不能新增 X 鎖
select… lock in share mode;insert into select …語句,對SELECT的表上掃描到的資料加LOCK_S鎖

X 鎖允許持有鎖的事務更新或刪除行。例:update、delete、select … from update
資料行被事務新增X鎖後,其他事務不能再為該行資料新增 任意型別的鎖。

我的實驗:似乎純粹的select語句(不帶lock in share mode或from update)沒有加任何鎖:
先執行session1:

BEGIN;
SELECT * FROM t03 where a = 10 for update;

再執行session2:

 select * from t03 lock in share mode;

此時因為session1佔用了排他鎖,所以session2想申請共享鎖也被阻塞。但如果session2執行的命令不是以上的,而是

 select * from t03;

則沒有阻塞的效果,馬上就返回了結果。

  • 間隙鎖,next-key鎖 效果等於鎖了全表?

特例:使用唯一索引的欄位查詢一行資料不使用間隙鎖。
另外,如果把事務隔離級別降級為讀已提交(Read Committed),間隙鎖會自動失效

例子:
先執行session1:

BEGIN;
select * from t01 for update;
或者為select * from t01 where b=任意值 for update;

再執行session2:

 insert into t01 values(5,6);

session2此時會被阻塞。注意表的主鍵為a,b上沒有索引,而a也沒有值為5的列。而如果把session中的select語句改為select * from t01 where a=非5的任意值 for update;,則session2不會被阻塞。

翻到網上有一篇https://www.cnblogs.com/aspirant/p/9177978.html,覺得講得比這裡清晰,關鍵有幾點:

  1. MVCC只是工作在兩種事務級別底下:Read Committed,Repeatable Read。因為其他兩種:READ UNCOMMITTED總是讀取最新的資料,不符合當前事務版本的資料行,而Serializable則會對所有的行加鎖。
  2. 按資料庫原始的事務的定義,Repeatable Read會出現幻讀的情況。但Mysql通過間隙鎖的機制可以保證即使在Repeatable Read級別下面也不會出現幻讀。
  3. 在MVCC併發控制中,讀操作可以分成兩類:快照讀 (snapshot read)與當前讀 (current read)。
    快照讀,讀取的是記錄的可見版本 (有可能是歷史版本),不用加鎖。
    當前讀,讀取的是記錄的最新版本,並且,當前讀返回的記錄,都會加上鎖,保證其他事務不會再併發修改這條記錄。
    在一個支援MVCC併發控制的系統中,哪些讀操作是快照讀?哪些操作又是當前讀呢?以MySQL InnoDB為例:
    快照讀:簡單的select操作,屬於快照讀,不加鎖。
    select * from table where ?;
    當前讀:特殊的讀操作,插入/更新/刪除操作,屬於當前讀,需要加鎖。
    select * from table where ? lock in share mode;
    select * from table where ? for update;
    insert into table values (…);
    update table set ? where ?;
    delete from table where ?;

《4.5.2.2-資料庫鎖-表級鎖》

  • MDL後設資料鎖,不依賴於任何儲存引擎
    在這裡插入圖片描述
  • 表鎖之獨佔鎖與共享鎖:
    在這裡插入圖片描述
  • 自增鎖是一種特殊的表級鎖

相關文章