20.2.1 RR级别+表无显式主键和索引
表及数据准备: create table t(id int(11) default null,name char(20) default null );
insert into t values(10,'donghongyu'),(20,'lichun'),(30,'luoxiaobo');
开启事务并采用for update(当前读):begin;
select * from t for update;
锁信息
1 t:table:IX:NULL 对表添加了IX锁:在获取表中某行的独占锁前,首先必须获取表的IX锁
2 、4条记录锁t:GEN_CLUST_INDEX:RECORD:X:supremum pseudo-record、0x00000000600-3
t:PRIMARY:X:10,20,30在表中3条记录上分别添加了Next-Key Lock锁(Lock mode字段显示的是X),防止有数据变化发生幻读,例如进行了更新、删除操作
PRIMARY:X:supremum pseudo- record 1条记录lock_date:supremum pseudo- record:在RR隔离级别下,为了防止发生幻读,会将最大索引值之后的间隙锁住并用“supremum pseudo-record”表示高于表中任何一个索引的值。
3、整体加锁顺序是:1 对表添加IX锁;2在“supremum”上添加Next-Key Lock锁;3 在GEN_CLUST_INDEX 3条记录上分别添加Next-Key Lock锁。
select *from t where id=10 for update;
锁信息与未带where条件一致。
为什么同样会有“supremum pseudo-record”?
如上例所示,虽然where 条件是id=10,但是每次插入记录时所产生的聚集索引(DB_ROW_ID)还是自增的,每次都会在表的最后插入,所以就有可能插入id=10这条记录。因此,需要添加一条“supremum pseudo-record”防止数据插入。
为什么有了where条件,但是还会在不满足where条件的记录上加Next-Key Lock锁呢?
主要是防止幻读。如果不添加Next-Key Lock锁,这时若有其他会话执行delete或者update语句,则会造成幻读。在READ-COMMITTED隔离级别下,对于不满足where条件的记录会释放的早一些。
20.2.2 RR级别+表有显式主键无索引
表及数据准备:create table dhytest(id int(11) not null,name char(20) default null,primary key (id)) engine=innoDB default charset=utf8;insert into dhytest values(10,'donghongyu'),(20,'lichun'),(30,'luoxiaobo');
不同情况加锁方式不同
不带where条件
锁信息与无主键无索引时相同。
where 条件是主键字段:where id=10
锁信息:2条锁记录
对表添加IX锁
PRIMARY:X,REC_NOT_GAP:10对主键添加了记录锁(X,REC_NOT_GAP),只锁住了where 条件id=10这条记录。因为主键已经保证了唯一性,所以在插入时就不会是ID=10这条记录了。因此这里不需要间隙锁。
where条件包含主键字段和非主键字段:where id=10 and name='donghongyu'
锁信息:加锁方式与where条件是主键字段的加锁方式相同,因为根据主键字段可以直接定位一条记录
对表添加IX锁
PRIMARY:X,REC_NOT_GAP:10 对主键添加了记录锁(X,REC_NOT_GAP),只锁住了where 条件id=10这条记录。因为主键已经保证了唯一性,所以在插入时就不会是ID=10这条记录了。因此这里不需要间隙锁。
where 条件是非主键字段呢?
20.2.3 RR级别+表无显式主键有索引
不带where条件
锁信息与无主键无索引时相同。
普通索引
where条件是索引字段
1 create index idx_id on t(id)
2 begin ; select * from t where id=10 for update;
锁信息
1、1条IX锁
2、t:idx_id:RECORD:X :10,0X000000001f00
3、t:GEN_CLUST_INDEX:RECORD:X,REC_NOT_GAP:0X000000001f00
4、t:idx_id:RECORD:X,GAP :20,0X000000001f01
加锁顺序:1 对表t添加IX锁;2 对id=10对应的索引添加next-Key lock锁,区间是(-无穷大,10】。3 对索引对应的聚集索引添加X记录锁。4,为防止幻读(因为是普通索引,所以可以再插入10=10这条记录),对索引记录区间(10,20)添加间隙锁。 这时如果插入id=9到id=19之间的记录都会被阻塞,而插入id=20这条记录则不会被阻塞,因为它不在间隙锁范围内。
begin;insert into t values(9,'hanjie');
锁信息
1 t:IX:NULL
2、idx_id:record:X,GAP,INSERT_INTENTION:10,0X000000001f00
3、t:IX:NULL
4、t:idx_id:RECORD:X:10,0x000000001F00
5、t:GEN_CLUST_INDEX:RECORD:X,REC_NOT_GAP:0x000000001F00
6、t:idx_id:RECORD:X,GAP:20,0X000000001F01
where条件包含索引字段和非索引字段
此情况与where条件是普通索引字段情况相同。
唯一索引
where条件是索引字段
drop index idx_id on t;create unique index idx_id on t (id)
begin,select * from t where id=10 for update;
锁信息
t:TABLE:IX
t:idx_id:RECORD:X,REC_NOT_GAP:10
与where条件是主键字段的加锁情况相同,表无显式主键则会把唯一索引作为主键,因为是主键,所以不能再插入id=10这条记录了。因此这里不需要间隙锁。
where条件包含索引字段和非索引字段
此情况与where条件是唯一所以字段的情况相同。
20.2.4 RR级别+表有显式主键和索引
表有显式主键和普通索引
create table t (id int(11) not null,name char(20) default null,primary key (id),key idx_name(name))engine=innodb default charset=utf8;
不带where条件
begin;select * from t for update;
锁信息
t:null:table:IX:NULL
t:idx_name:record:x:supremumpseudo-record
3 条 t:idx_name:record:X:'NAME',10、’NAME',20、‘name',30
3条t:PRIMARY:RECORD:X,REC_NOT_GAP:10、20、30
加锁顺序:1、对表添加IX锁2、对supremum pseudo-record 添加Next-Key Lock锁3、对索引添加Next-Key Lock锁 4、对主键索引添加X记录锁。
where条件是普通索引字段
select * from t where name='donghongyu' for update;
锁信息
1 t:TABLE:IX:NULL
t:idx_name:RECORD:X:'donghongyu',10
t:PRIMARY:RECORD:X:10
t:idx_name:RECORD:X,GAP:'lichun',20
此情况与 ’表无显式主键有索引“‘的”where条件是索引字段“情况相同,只因索引字段不同,加锁的是name字段而已。
where条件是主键字段
此情况与”20.2.2 RR级别+表有显式主键无索引 “中的”where条件是主键字段“情况相同
where条件同时包含普通索引字段和主键字段
在这种情况下,要看SQL执行计划用到的是主键索引还是普通索引
主键索引
则与“20.2.2 RR级别+表有显式主键无索引”节中的”where条件是主键字段“情况相同。
普通索引
则与”20.2.3节RR级别+表无显式主键有索引“中”where条件是索引字段“情况相同,只因索引字段名称不同,加锁的是name字段而已。
表有显示主键和唯一索引
不带where条件
此情况与“20.2.4节RR级别+表有显式主键和索引”中的”不带where条件“的加锁情况相同。
where 条件是唯一索引字段
此情况与“20.2.3节RR级别+表无显式主键有索引”中的”where条件是索引字段“的加锁情况相同。
where条件是主键字段
此情况与“20.2.2节RR级别+表有显式主键无索引”中的”where条件是主键字段“的加锁情况相同。
where条件同时包含唯一索引字段和主键字段
在这种情况下,要看SQL执行计划用到的是主键索引还是普通索引
主键索引
则与“20.2.2 RR级别+表有显式主键无索引”节中的”where条件是主键字段“情况相同。
普通索引
则与”20.2.3节RR级别+表无显式主键有索引“中”where条件是索引字段“情况相同,只因索引字段名称不同,加锁的是name字段而已。
「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




