MYSQL中鎖的分類與加鎖方式小結(jié)
在數(shù)據(jù)庫并發(fā)環(huán)境中,多個事務(wù)可能同時訪問同一份數(shù)據(jù)。如果沒有合理的并發(fā)控制機(jī)制,就會出現(xiàn)數(shù)據(jù)不一致、臟讀、幻讀等問題。
為了解決這些問題,MySQL 在存儲引擎層提供了一套完整的 鎖機(jī)制(Lock Mechanism),用于控制多個事務(wù)對數(shù)據(jù)的訪問順序。
從整體結(jié)構(gòu)上看,MySQL 的鎖可以按照 鎖的粒度 分為兩大類:
MySQL 鎖
│
├── 表級鎖
│ ├── 表鎖(LOCK TABLES)
│ ├── 元數(shù)據(jù)鎖(MDL Lock)
│ └── 意向鎖(Intention Lock)
│
└── 行級鎖(InnoDB)
├── 記錄鎖(Record Lock)
├── 間隙鎖(Gap Lock)
└── 臨鍵鎖(Next-Key Lock)下面分別進(jìn)行介紹。
一、表級鎖(Table Lock)
表級鎖是 作用在整張表上的鎖,也就是說,一旦某個事務(wù)對表加鎖,其他事務(wù)訪問該表就會受到限制。
表級鎖的特點(diǎn):
- 加鎖速度快
- 實(shí)現(xiàn)簡單
- 鎖粒度大
- 并發(fā)能力較低
MySQL 中表級鎖主要包括三種:
- 顯式表鎖
- 元數(shù)據(jù)鎖(MDL)
- 意向鎖
1 顯式表鎖(LOCK TABLES)
顯式表鎖是通過 SQL 語句手動對表加鎖:
LOCK TABLES table_name READ; LOCK TABLES table_name WRITE;
釋放鎖:
UNLOCK TABLES;
1.1 READ 鎖(讀鎖)
LOCK TABLES user READ;
含義:
- 當(dāng)前事務(wù)可以讀取表數(shù)據(jù)
- 不允許修改數(shù)據(jù)
- 其他事務(wù)可以繼續(xù)獲取 READ 鎖
- 其他事務(wù)不能獲取 WRITE 鎖
也就是說:
讀讀可以并發(fā),讀寫互斥。
1.2 WRITE 鎖(寫鎖)
LOCK TABLES user WRITE;
含義:
- 當(dāng)前事務(wù)可以讀寫表
- 其他事務(wù)既不能讀也不能寫
- 直到執(zhí)行
UNLOCK TABLES
因此 WRITE 鎖是 排他鎖。
2 元數(shù)據(jù)鎖(MDL Lock)
MDL(Metadata Lock)是 MySQL 自動維護(hù)的一種鎖,不需要手動加鎖。
它的作用是:
防止在執(zhí)行 DML 操作時表結(jié)構(gòu)被修改。
例如:
執(zhí)行查詢:
SELECT * FROM user;
MySQL 會自動添加:MDL 讀鎖
如果執(zhí)行:
ALTER TABLE user ADD COLUMN age INT;
MySQL 會添加:MDL 寫鎖
MDL 寫鎖會阻塞其他事務(wù)的讀寫操作,從而避免 DDL 與 DML 沖突。
在生產(chǎn)環(huán)境中,如果一個事務(wù)長時間未提交,可能會導(dǎo)致:
ALTER TABLE 一直等待
這往往就是 MDL 鎖導(dǎo)致的阻塞問題。
3 意向鎖(Intention Lock)
意向鎖是 InnoDB 在 表級別維護(hù)的一種鎖標(biāo)記,用于配合行鎖使用。
它的核心作用是:
在事務(wù)對某一行數(shù)據(jù)加鎖之前,先在表級別聲明加鎖意圖。
例如:
SELECT * FROM user WHERE id = 1 FOR UPDATE;
InnoDB 會做兩件事:
1?? 在表上加 意向排他鎖(IX)
2?? 在對應(yīng)記錄上加 行排他鎖(X鎖)
3.1 意向鎖分類
意向鎖(Intention Lock)不是只有 IX 一種,而是一個鎖的類別,其中包括兩種類型:
- IS(Intention Shared Lock)意向共享鎖
- IX(Intention Exclusive Lock)意向排他鎖
也就是說:
| 鎖類型 | 含義 |
|---|---|
| IS | 表示事務(wù)準(zhǔn)備在某些行上加 共享鎖(S鎖) |
| IX | 表示事務(wù)準(zhǔn)備在某些行上加 排他鎖(X鎖) |
舉個例子
1?? 查詢加共享鎖
SELECT * FROM user WHERE id = 1 LOCK IN SHARE MODE;
InnoDB 會:
表:IS 行:S
2?? 更新數(shù)據(jù)
UPDATE user SET age = 20 WHERE id = 1;
InnoDB 會:
表:IX 行:X
3.2 為什么需要意向鎖?
假設(shè)沒有意向鎖:
當(dāng)一個事務(wù)想給整張表加鎖時,就必須掃描整張表,查看是否存在行鎖,這樣效率非常低。
而有了意向鎖之后:
只需要檢查表級鎖即可判斷是否存在行鎖。
因此:
意向鎖的本質(zhì)是 用于快速判斷表中是否存在行鎖的標(biāo)記。
一句話總結(jié):意向鎖(Intention Lock)是 InnoDB 在表級維護(hù)的一種鎖標(biāo)記,用于表示事務(wù)即將在某些行上加鎖,其主要類型包括意向共享鎖(IS)和意向排他鎖(IX)。
二、行級鎖(Row Lock)
行級鎖是 InnoDB 存儲引擎支持的一種鎖機(jī)制。
相比表鎖,它的特點(diǎn)是:
- 鎖粒度更小
- 并發(fā)能力更強(qiáng)
- 更適合高并發(fā)系統(tǒng)
行鎖鎖定的是 一條具體記錄,而不是整張表。
1 記錄鎖(Record Lock)
記錄鎖是最基本的行鎖,它只鎖定某一條記錄。
例如:
SELECT * FROM user WHERE id = 1 FOR UPDATE;
只會鎖?。?/p>
id = 1 這一條記錄
其他記錄仍然可以被訪問。
記錄鎖通常分為:
- S 鎖(共享鎖)
- X 鎖(排他鎖)
它們滿足:
讀讀可以并發(fā) 讀寫互斥 寫寫互斥
2 間隙鎖(Gap Lock)
間隙鎖鎖住的不是具體記錄,而是 索引之間的空隙。
例如:
SELECT * FROM user WHERE score > 100 FOR UPDATE;
如果當(dāng)前數(shù)據(jù)為:
100 150 200
間隙鎖可能鎖?。?/p>
(100 , +∞)
這樣其他事務(wù)就 不能插入 score=120 的數(shù)據(jù)。
間隙鎖的主要作用是:
防止幻讀。
需要注意:
間隙鎖 不會鎖住已有記錄,只鎖住區(qū)間。
3 臨鍵鎖(Next-Key Lock)
Next-Key Lock 是:
Record Lock + Gap Lock
也就是說:
既鎖住記錄,又鎖住間隙。
例如:
SELECT * FROM user WHERE age BETWEEN 20 AND 30 FOR UPDATE;
假設(shè)表中存在:
20 25 30
InnoDB 可能鎖?。?/p>
(-∞,20] (20,25] (25,30] (30,+∞)
這樣不僅鎖住已有記錄,還鎖住記錄之間的間隙。
因此:
Next-Key Lock 可以徹底防止幻讀。
到此這篇關(guān)于MYSQL中鎖的分類與加鎖方式小結(jié)的文章就介紹到這了,更多相關(guān)mysql鎖的分類與加鎖內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL數(shù)據(jù)庫聚合查詢和聯(lián)合查詢詳解
聚合查詢就是在一個表里通過聚合函數(shù)進(jìn)行查詢操作,通常是求和,求平均值等操作,這篇文章主要介紹了MySQL聚合查詢和聯(lián)合查詢的相關(guān)資料,需要的朋友可以參考下2024-03-03
MySQL創(chuàng)建和刪除數(shù)據(jù)庫的命令及相關(guān)PHP腳本的操作方法
這篇文章主要介紹了MySQL創(chuàng)建和刪除數(shù)據(jù)庫的命令及相關(guān)PHP腳本的操作方法,這里主要講述Linux中在mysqladmin下的命令操作,需要的朋友可以參考下2015-11-11
Windows XP系統(tǒng)安裝MySQL5.5.28圖解教程
很多朋友在winxp系統(tǒng)中開發(fā)php等,需要安裝mysql數(shù)據(jù)庫,這里簡單介紹下,如何在xp下安裝mysql軟件,其實(shí)跟其它系統(tǒng)都差不多,主要是軟件對系統(tǒng)的兼容性2013-05-05
關(guān)于MySQL的整型數(shù)據(jù)的內(nèi)存溢出問題的應(yīng)對方法
這篇文章主要介紹了關(guān)于MySQL的整型數(shù)據(jù)的內(nèi)存溢出問題的應(yīng)對方法,作者還列出了MySQL所支持的整型數(shù)據(jù)的存儲空間支持大小,需要的朋友可以參考下2015-05-05
Mysql刪除重復(fù)的數(shù)據(jù) Mysql數(shù)據(jù)去重復(fù)
這篇文章主要介紹了Mysql刪除重復(fù)的數(shù)據(jù) Mysql數(shù)據(jù)去重復(fù),需要的朋友可以參考下2016-08-08

