MySQL的併發處理機制,有MVCC及鎖機制來處理,上篇簡要說明了 MVCC及隔離級別:mysql的併發處理機制_上篇 ,這篇來講說mysql下的鎖。html
類型 | 說明 | 場景 |
S | 共享鎖 | 針對於RS隔離級別的查詢或者添加Lock in share mode的SELECT查詢而產生的鎖 |
X | 排它鎖 | 針對於update、delete、insert操做而產生的鎖 |
IS | 意向共享鎖 | 表級別的鎖,在添加S鎖以前對錶格添加IS鎖 |
IX | 意向排他鎖 | 表級別的鎖,在添加X鎖以前對錶格添加IX鎖 |
age
|
2
|
4
|
7
|
9
|
21
|
25
|
id
|
1
|
4
|
5
|
2
|
3
|
6
|
id
|
1
|
2
|
3
|
4
|
5
|
6
|
age
|
2
|
9
|
21
|
4
|
7
|
25
|
name
|
null
|
null
|
null
|
null
|
null
|
null
|
表格 SQL
|
select * from tbname
where age/id ...
|
update tbname set name=...
where id = 4
|
update tbname set name=...
where age = 21
|
update tbname set name=...
where age between 5 and 15
|
tb_no_index
|
讀不加鎖,讀未提交數據
可能有髒讀、不可重複讀及幻讀
|
當前讀,根據主鍵修改數據
tbname 加意向表鎖 IX
id=4 加 行鎖 X
|
表格的age列無索引,因此update過程當中,全表加X鎖
支持semi-constent-read,若是有其餘update語句修改其餘行不堵塞,可是不支持 select ... for update
|
同左
|
tb_index
|
表格的age列有索引,update過程當中
tb_index 加 表格意向鎖 IX
age索引上面,age=21 行添加行鎖 X
再在主鍵上,給id=3 這一行數據,添加行數 X
|
表格的age列有索引,update過程涉及age=7,9 兩行數據
tb_index 加表格意向鎖 IX
age索引上面,age=7,age=9 行添加行鎖 X
再在主鍵上,給id=2,id=5 這一行數據,添加行數 X
|
||
tb_unique_index
|
同上
|
同上
|
表格
SQL
|
select * from tbname
where age/id ...
|
update tbname set name=...
where id = 4
|
update tbname set name=...
where age = 21
|
update tbname set name=...
where age between 5 and 15
|
tb_no_index
|
快照讀,不加鎖
讀取的數據不必定是最新版本,可是事務內的全部查詢讀取數據都是同一版本的行數據,不存在髒讀、不可重複讀及幻讀的狀況
|
當前讀,根據主鍵修改數據
tbname 加意向表鎖 IX
id=4 加 行鎖 X
|
表格的age列無索引,因此update過程當中,全表加X鎖
支持semi-constent-read,若是有其餘update語句修改其餘行不堵塞,可是不支持 select ... for update
|
同左
|
tb_index
|
表格的age列有索引,update過程當中
tb_index 加 表格意向鎖 IX
age索引上面,age=21 行添加行鎖 X
再在主鍵上,給id=3 這一行數據,添加行數 X
|
表格的age列有索引,update過程涉及age=7,9 兩行數據
tb_index 加表格意向鎖 IX
age索引上面,age=7,age=9 行添加行鎖 X
再在主鍵上,給id=2,id=5 這一行數據,添加行數 X
|
||
tb_unique_index
|
同上
|
同上
|
表格 SQL
|
select * from tbname
where age/id ...
|
update tbname set name=...
where id = 4
|
update tbname set name=...
where age = 21
|
update tbname set name=...
where age between 5 and 15
|
tb_no_index
|
快照讀,不加鎖
讀取的數據不必定是最新版本,可是事務內的全部查詢讀取數據都是同一版本的行數據,不存在髒讀、不可重複讀及幻讀的狀況
|
當前讀,根據主鍵修改數據
tbname 加意向表鎖 IX
id=4 加 行鎖 X
|
表格的age列無索引,因此update過程當中
全表加X鎖,期間全表堵塞UPDATE\DELETE\INSERT
|
同左
|
tb_index
|
表格的age列有索引,update過程當中
tb_index 加 表格意向鎖 IX
age索引上面,age=21 行添加行鎖 X
再在主鍵上,給id=3 這一行數據,添加行數 X
你覺得結束了!並無,這裏有趣了!
還會添加兩個gap lock ((9,2) ,(21,3)),((21,3), (21,25))
這裏咱們單獨拎出小表格來分析。
|
表格的age列有索引,update過程涉及age=7,9 兩行數據
tb_index 加表格意向鎖 IX
age索引上面,age=7,age=9 行添加行鎖 X
再在主鍵上,給id=2,id=5 這一行數據,添加行數 X
同時會在索引 age的值上添加 3個 gap lock,分別爲
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
|
||
tb_unique_index
|
覺得跟上面的加鎖範圍同樣,no no no
惟一索引列上 每個age都是惟一的,也就是age=21只有一個,不會再INSERT一個新的 age =21進來,故在這裏不須要加gap lock,加鎖狀況以下:
tb_index 加 表格意向鎖 IX
age=21 行添加行鎖 X
age索引上面,age=21 行添加行鎖 X
再在主鍵上,給id=3 這一行數據,添加行數 X
|
表格的age列有索引,update過程涉及age=7,9 兩行數據
tb_index 加表格意向鎖 IX
age索引上面,age=7,age=9 行添加行鎖 X
再在主鍵上,給id=2,id=5 這一行數據,添加行數 X
同時會在索引 age的值上添加 3個 gap lock,分別爲
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
可是,範圍查詢添加到gap lock在其餘狀況下跟非惟一索引會有一些差異,能夠看下錶的例子。
|
update tbname set name=...
where age between 1 and 7
|
update tbname set name=...
where age between 2 and 7
|
update tbname set name=...
where age between 5 and 10
|
update tbname set name=...
where age between 15 and 50
|
|
tb_index
|
(-∞,2),(2,4),(4,7),(7,9)
|
(-∞,2),(2,4),(4,7),(7,9)
|
(4,7),(7,9),(9,21)
|
(9,21),(21,25),(25,+∞)
|
tb_unique_index
|
(-∞,2),(2,4),(4,7)
|
(2,4),(4,7)
|
(4,7),(7,9),(9,21)
|
(9,21),(21,25),(25,+∞)
|
表格 SQL
|
select * from tbname
where age/id ...
|
update tbname set name=...
where id = 4
|
update tbname set name=...
where age = 21
|
update tbname set name=...
where age between 5 and 15
|
tb_no_index
|
不支持快照讀,全部SELECT都是當前讀,全部SELECT操做都須要加S鎖,除主鍵定值查找\惟一索引定值查找外,其餘基於索引或者主鍵的範圍查找都會添加 S GAP LOCK。併發度是四個隔離級別中性能最差的。
|
當前讀,根據主鍵修改數據
tbname 加意向表鎖 IX
id=4 加 行鎖 X
|
表格的age列無索引,因此update過程當中
全表加X鎖,期間全表堵塞UPDATE\DELETE\INSERT
|
同左
|
tb_index
|
表格的age列有索引,update過程當中
tb_index 加 表格意向鎖 IX
age索引上面,age=21 行添加行鎖 X
再在主鍵上,給id=3 這一行數據,添加行數 X
在age索引上 添加兩個gap lock ((9,2) ,(21,3)),((21,3), (21,25))
|
表格的age列有索引,update過程涉及age=7,9 兩行數據
tb_index 加表格意向鎖 IX
age索引上面,age=7,age=9 行添加行鎖 X
再在主鍵上,給id=2,id=5 這一行數據,添加行數 X
同時會在索引 age的值上添加 3個 gap lock,分別爲
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
|
||
tb_unique_index
|
惟一索引列上 每個age都是惟一的,也就是age=21只有一個,不會再INSERT一個新的 age =21進來,故在這裏不須要加gap lock,加鎖狀況以下:
tb_index 加 表格意向鎖 IX
age=21 行添加行鎖 X
|
表格的age列有索引,update過程涉及age=7,9 兩行數據
tb_index 加表格意向鎖 IX
age索引上面,age=7,age=9 行添加行鎖 X
再在主鍵上,給id=2,id=5 這一行數據,添加行數 X
同時會在索引 age的值上添加 3個 gap lock,分別爲
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
可是,範圍查詢添加到gap lock在其餘狀況下跟非惟一索引會有一些差異,能夠看下錶的例子。
|
表格 SQL
|
select * from tbname
where id=5
|
select * from tbname
where id betwee 5 and 15
|
select * from tbname
where age=21
|
select * from tbname
where age betwee 5 and 9
|
tb_no_index
|
主鍵定值查找
表格tbname 添加 IS 意向鎖
id=5 添加 S鎖
|
主鍵範圍查找
表格tbname 添加 IS 意向鎖
id=5,id=6 兩行數據 添加 S鎖
同時添加2個 S GAP LOCK ,分別爲 ((5,7),(6,25))跟((6,25),+∞)
|
全表查找
表格 tbname 添加 IS 意向鎖
因爲全表查找,整個表格 再次添加 S 表鎖
|
全表查找
表格 tbname 添加 IS 意向鎖
因爲全表查找,整個表格 再次添加S 表鎖
|
tb_index
|
ix_age索引查找
表格tbname 添加 IS 意向鎖
索引上 age = 21 添加 S 行鎖
主鍵上 id=3 添加 S 行鎖
同時添加 2個
S GAP LOCK ,分別爲 ((9,2) ,(21,3)),((21,3), (21,25))
|
ix_age索引查找
表格tbname 添加 IS 意向鎖
age索引上面,age=7,age=9 行添加行鎖 S
再在主鍵上,給id=2,id=5 這一行數據,添加行數 S
同時會在索引 age的值上添加 3個 S gap lock,分別爲
((4,4),(7,5))、((7,5),(9,2))、((9,2),(21,3))
|
||
tb_unique_index
|
ix_age索引查找
表格tbname 添加 IS 意向鎖
索引上 age = 21 添加 S 行鎖
主鍵上 id=3 添加 S 行鎖
因爲age列惟一,故不須要添加GAP LOCK
|
ix_age索引查找
表格tbname 添加 IS 意向鎖
age索引上面,age=7,age=9 行添加行鎖 S
再在主鍵上,給id=2,id=5 這一行數據,添加行數 S
同時會在索引 age的值上添加
2 個 S gap lock,分別爲
((4,4),(7,5))、((7,5),(9,2))
|