共享鎖(讀鎖)/排他鎖(寫鎖)
阿新 • • 發佈:2021-08-16
讀鎖與寫鎖區別
語法
// 讀鎖
select ... lock in share mode
// 寫鎖
select ... for update
共同點
- 都是作用在 select 語句中
- A 事務對某 select 語句加鎖之後(未提交事務),其他事務無法對該資料執行修改操作(update/delete)
- 只有當 A 事務提交或回滾,其他事務才能對資料進行修改操作(update/delete)
- 不管讀鎖還是寫鎖,它們都屬於悲觀鎖的一種形式
不同點
- 讀鎖:當 A 事務對 select 語句加上讀鎖時,其他事務對 select 加上讀鎖獲取資料不會阻塞
- 寫鎖:當 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;