一、什么是鎖
鎖是數據庫系統區別于文件系統的一個關鍵特性。鎖機制用于管理對共享資源的并發訪問。
?
二、MySQL 不同存儲引擎支持的鎖機制
?
存儲引擎 | 支持的鎖類型 |
Myisam | 表鎖 |
Innodb | 行鎖、表鎖 |
Memory | 表鎖 |
BDB | 頁鎖、表鎖 |
表鎖:直接鎖住的是一個表,開銷小,加鎖快,不會出現死鎖的情況,鎖定粒度大,發生鎖沖突的概率更高,應對并發能力最低。(因為加鎖了,所以經常需要等待)
行鎖:直接鎖住的是一條記錄,開銷大,加鎖慢,發生鎖沖突的概率較低,應對并發能力很高。
頁鎖:鎖住的一個頁面,在 InnoDB 中一個頁面為16KB,它的開銷介于表級鎖和行級鎖中間,也可能會出現死鎖,鎖定粒度也介于表級鎖和行級鎖中間,應對并發能力介于表級鎖和行級鎖中間。
?
?三、InnoDB 存儲引擎中的鎖
InnoDB 支持的是行級鎖和表級鎖。但是 InnoDB 實際上是實現了 6 種鎖。
1、實現了兩種標準的** 行級鎖**,分別是 **共享鎖、排他鎖**。
2、實現了兩種標準的** 表級鎖**,分別是 **意向共享鎖、意向排他鎖**。
3、實現了兩種抽象的鎖,樂觀鎖、悲觀鎖。(這兩種鎖并不是真實存在的)
?
?四、InnoDB 存儲引擎中 各種鎖的加鎖示例
1、加共享鎖示例:
-- 事務 T1
BEGIN;
START TRANSACTION;
select * from user where id = 1 LOCK IN SHARE MODE;-- COMMIT;
-- 事務 T2-- 不加鎖的查詢 (可以查詢到)
-- SELECT * from user where id = 1;-- 不加鎖的更新 (不可以更新)
-- UPDATE `user` set age = 29 where id = 1;-- 加共享鎖的查詢 (可以查詢到)
-- SELECT * from user WHERE id = 1 LOCK IN SHARE MODE;-- 加排他鎖的查詢 (不可以查詢)
-- SELECT * from user WHERE id = 1 FOR UPDATE;
如果在事務 T1 中對行記錄加了共享鎖,那么其他事務 T2,不論加沒加鎖,都不能更新,直到事務 T1 釋放鎖。
如果在事務 T1 中對行記錄加了共享鎖,事務 T2 是沒有加鎖的查詢,或者加的是共享鎖的查詢,則可以查詢到結果。
如果在事務 T1 中對行記錄加了共享鎖,事務 T2 是加了排它鎖的查詢,則暫時不能查詢,直到事務 T1 釋放鎖。
?
2、加排他鎖示例
-- 事務T1
BEGIN;
START TRANSACTION;
select * from user where id = 1 FOR UPDATE;COMMIT;
-- 事務 T2-- 不加鎖的查詢 (可以查詢到)
-- SELECT * from user where id = 1;-- 不加鎖的更新 (不可以更新)
-- UPDATE `user` set age = 29 where id = 1;-- 加共享鎖的查詢 (不可以查詢到)
-- SELECT * from user WHERE id = 1 LOCK IN SHARE MODE;-- 加排他鎖的查詢 (不可以查詢到)
-- SELECT * from user WHERE id = 1 FOR UPDATE;
如果在事務 T1 中對行記錄加了排他鎖,那么其他事務T2,如果是不加鎖的查詢,是可以查詢到結果的,但如果是加鎖的查詢或更新,則不允許操作,直到事務 T1 釋放鎖。
注:凡是更新、刪除、插入操作,Mysql都會默認給這個操作加上排他鎖,所以這里只演示查詢操作的。
3、加意向共享鎖
對一個數據行加共享鎖(S),首先 InnoDB 會先找到這張表,對該表加意向共享鎖(IS)之后,再對該數據行添加共享鎖。意向共享鎖和意向排他鎖都是系統自動添加和自動釋放的,整個過程無需人工干預。
4、加意向排他鎖
對一個數據行加排他鎖(X),首先 InnoDB 會先找到這張表,對該表加意向排他鎖(IX)之后,再對該數據行添加排它鎖。意向共享鎖和意向排他鎖都是系統自動添加和自動釋放的,整個過程無需人工干預。
5、關于樂觀鎖和悲觀鎖的說明
樂觀鎖和悲觀鎖并不是真實存在的鎖,它們只是抽象出來的,對鎖的使用情況的描述。
6、悲觀鎖 *
悲觀鎖的特點是先獲取鎖,再進行業務操作,即“悲觀”的認為獲取鎖是非常有可能失敗的,因此要先確保獲取鎖成功再進行業務操作。通常所說的“一鎖二查三更新”即指的是使用悲觀鎖。通常來講在數據庫上的悲觀鎖需要數據庫本身提供支持,即通過常用的select … for update 操作來實現悲觀鎖。
7、樂觀鎖
樂觀鎖的特點是先進行業務操作,不到萬不得已不去拿鎖。即“樂觀”的認為拿鎖多半是會成功的,因此在進行完業務操作需要實際更新數據的最后一步再去拿一下鎖就好。樂觀鎖在數據庫上的實現完全是邏輯的,不需要數據庫提供特殊的支持。
?
原文鏈接:https://www.haveyb.com/article/63