1. 程式人生 > 其它 >共享鎖(讀鎖)/排他鎖(寫鎖)

共享鎖(讀鎖)/排他鎖(寫鎖)

讀鎖與寫鎖區別

語法

// 讀鎖
select ... lock in share mode
// 寫鎖
select ... for update

共同點

  1. 都是作用在 select 語句中
  2. A 事務對某 select 語句加鎖之後(未提交事務),其他事務無法對該資料執行修改操作(update/delete)
  3. 只有當 A 事務提交或回滾,其他事務才能對資料進行修改操作(update/delete)
  4. 不管讀鎖還是寫鎖,它們都屬於悲觀鎖的一種形式

不同點

  1. 讀鎖:當 A 事務對 select 語句加上讀鎖時,其他事務對 select 加上讀鎖獲取資料不會阻塞
  2. 寫鎖:當 A 事務對 select 語句加上寫鎖時,其他事務對 select 加上讀鎖/寫鎖獲取資料阻塞,只有等待 A 事務提交或回滾,其他事務才能讀取到資料

讀鎖寫鎖示例

假設有張 user 表,表中資料如下

讀鎖(共享鎖)

------------------A事務------------------ ------------------B事務------------------
對 id = 1 的資料增加讀鎖,但是並不提交事務
不加鎖的查詢,查詢成功
加上讀鎖查詢,查詢成功
對 id = 2 的資料進行修改,修改成功
對 id = 1 的資料進行修改,修改出現阻塞
事務提交
由於 A事務 commit 了,阻塞狀態取消,修改成功

寫鎖(排他鎖)

------------------A事務------------------ ------------------B事務------------------
對 id = 1 的資料增加寫鎖,但是並不提交事務
不加鎖的查詢,查詢成功
加上寫鎖查詢 id = 2 的資料,查詢成功
加上寫鎖查詢 id = 1 的資料,查詢出現阻塞
事務提交
由於 A事務 commit 了,阻塞狀態取消,查詢成功
對 id = 1 的資料增加寫鎖,但是並不提交事務
修改 id = 2 的資料,修改成功
修改 id = 1 的資料,修改出現阻塞
事務提交
由於 A事務 commit 了,阻塞狀態取消,修改成功

注意事項

注意注意注意:for update 僅適用於InnoDB,並且必須開啟事務,在begin與commit之間才生效。或者在程式碼中使用@Transactional才能生效。

行鎖:訪問資料庫的時候,鎖定整個行資料,防止併發錯誤。 如InnoDB儲存引擎使用行鎖
表鎖:訪問資料庫的時候,鎖定整個表資料,防止併發錯誤。 如MyISAM儲存引擎使用表鎖

例1:明確指定主鍵,並且資料真實存在,行鎖

select status from t_goods where id = 1 for update;

例2:明確指定主鍵,但資料不存在,無鎖

select status from t_goods where id = 0 for update;

例3:主鍵不明確,表鎖

select status from t_goods where id <= 3 for update;

例4:無主鍵,表鎖

select status from t_goods for update;