mysql鎖分類
基於鎖的屬性分類:共享鎖(讀鎖)、排他鎖(寫鎖)
基於鎖的粒度分類:行級鎖(innodb)、表鎖(innodb、myisam)、頁級鎖(innodb引擎)、記錄鎖、間隙鎖、臨建鎖。
mysql中的絕大部分鎖都是悲觀鎖,按照粒度可以分爲行鎖和表鎖:
行鎖:
共享鎖:當讀取一行記錄的時候,爲了防止別人修改,則需要添加S鎖
排它鎖:當修改一行記錄的時候,爲了防止別人同時進行修改,則需要添加X鎖
X |
S |
|
X |
不兼容 |
不兼容 |
S |
不兼容 |
兼容 |
記錄鎖:添加在行索引上的鎖
間隙鎖:鎖定範圍是索引記錄之間的間隙,針對可重複讀以上隔離級別
臨鍵鎖:記錄鎖+間隙鎖
表鎖:
意向鎖:在獲取某行的鎖之前,必須要獲取表的鎖,分爲意向共享鎖,意向排它鎖
自增鎖:對自增字段所採用的特殊表級鎖。
鎖模式的含義:
IX:意向排它鎖
X:鎖定記錄本身和記錄之前的間隙(重點用)
S:鎖定記錄本身和記錄之前的間隙
X,REC_NOT_GAP:只鎖定記錄本身(重點用)
S,REC_NOT_GAP:只鎖定記錄本身
X,GAP:間隙鎖,不鎖定記錄本身(重點用)
S,GAP:間隙鎖,不鎖定記錄本身
X,GAP,INSERT_INTENTION:插入意向鎖
監控鎖:
show engine innodb status\G //顯示鎖
加鎖場景:
分情況來說主要是RR和RC的區別:
先介紹RR下的查詢鎖場景
查詢格式:
- select * from table for update
- select * from table where id ='10' for update
- select * from table where name ='10' for update
- RR+表無顯式主鍵沒有索引
初始化sql:
create table t1(id int default null, name char(20) default null);
insert into t1 values ( 10, '10' ),(20,'20' ),(30, '30’) ;
結論:
查詢1和查詢2(id不是索引列)加鎖一致:
加的是:臨鍵鎖 (-∞,10],(10,20],(20,30],(30,+∞), 所以鎖的是表,插入新數據超時,爲了組織幻讀問題。
2.RR+表有顯式主鍵沒有索引
初始化sql:
create table t2(id int primary key not null, name char(20) default null);
insert into t2 values ( 10, '10' ),(20,'20' ),(30, '30’) ;
結論:
查詢1:加的是:臨鍵鎖 (-∞,10],(10,20],(20,30],(30,+∞),
查詢2:加的是:id=10的行鎖,保證10的主鍵不能再插入了
3.RR+表無顯式主鍵有索引
初始化sql:
create table t3(id int default null, name char(20) default null);
create index idx_id on t3 (id);
insert into t3 values ( 10, '10' ),(20,'20' ),(30, '30’) ;
結論:
查詢1(鎖的row_id):加的是:臨鍵鎖 (-∞,10],(10,20],(20,30],(30,+∞),
查詢2:加的是:1.臨鍵鎖:(-∞,10],2.索引:10 ,3.間隙鎖:(10,20),減少幻讀的可能,插入小於20不允許。
4.RR+表無顯式主鍵有唯一索引
初始化sql:
create table t4(id int default null, name char(20) default null);
create unique idx_id on tt (id);
insert into t4 values ( 10, '10' ),(20,'20' ),(30, '30’) ;
結果:
查詢1(鎖的row_id):加的是:臨鍵鎖 (-∞,10],(10,20],(20,30],(30,+∞),
查詢2:加的是: 行鎖:10被鎖定
5.RR+表有顯式主鍵有索引
初始化sql:
create table t5(id int not null, name char(20) default null,primary key(id),key idx_name(name));
create unique idx_id on tt (id);
insert into t5 values ( 10, '10' ),(20,'20' ),(30, '30’) ;
結果:
查詢1(鎖的row_id):加的是:臨鍵鎖 (-∞,10],(10,20],(20,30],(30,+∞);以及10 20 30 的行鎖
查詢2:加的是: 行鎖
查詢3:加的是:
臨鍵鎖:(-∞,10],
索引:10
間隙鎖:(10,20),
6.RR+表有顯式主鍵有唯一索引
初始化sql:
create table t6(id int not null,name char(20) default null,primary key(id) , nique key idx_name(name);
insert into t6 values ( 10, '10' ),(20,'20' ),(30, '30’) ;
結果:
查詢1(鎖的row_id):加的是:加的是:臨鍵鎖 (-∞,10],(10,20],(20,30],(30,+∞);以及10 20 30 的行鎖
查詢2:加的是: 行鎖
RC情況下查詢1和2---都是行鎖(因爲臨建鎖和間隙鎖都是解決幻讀問題)
1.RC+表無顯式主鍵沒有索引
2.RC+表有顯式主鍵沒有索引
3.RC+表無顯式主鍵有索引
4.RC+表無顯式主鍵有唯一索引
5.RC+表有顯式主鍵有索引
6.RC+表有顯式主鍵有唯一索引