GreatSQL社区

搜索

[讨论中] RC隔离级别下的加锁问题咨询

67 4 2024-7-6 20:47
RC隔离级别下:
PK|C1|C2
1|1|1
2|1|2
3|1|3
4|1|4

c1列有索引IDX_C1

update t set c2=5 where c1=1 and c2=2;
加锁顺序:
1.IDX_C1上4行全要加锁
那么第二步:
回表在主键PK=2上加锁?
还是要先在PK1,2,3,4上加锁,最后退化成只在PK=2上加锁?


全部回复(4)
yejr 2024-7-6 20:50:31
二者没区别,innodb是聚集索引组织表,锁住了PK和锁住一整行没两样
fancyghost 2024-7-7 17:16:59
yejr 发表于 2024-7-6 20:50
二者没区别,innodb是聚集索引组织表,锁住了PK和锁住一整行没两样

create table t2 (
id int primary key,
c1 int,
c2 int,
c3 int,
key idx_c1(c1))
;

insert into t2 values
(1,1,1,1),
(2,2,2,2),
(3,2,3,3),
(4,4,4,4);


S1:先执行
begin;
update t2 set c3=99 where id=3;
获取了主键3上的锁

S2:
begin;
update t2 set c3=66 where c1=2 and c2=2;
本身和主键3没关系了,但是会被阻塞。说明S2在锁完IDX_C1的 2(c1)-2(PK);2(c1)-3(pk)后就要去锁对应的主键2和3,结果发现3被S1就阻塞了;


c1列有索引
where c1=2 and c2=3
c1=2的有两行记录,这两行记录上c2=2和c2=3

那通过这个条件的加锁过程如下,都按rc隔离级别考虑
1.c1索引的两条记录都加锁
2.这两条记录的主键也都需要加锁
3.根据c2的值发现(2-2)这个主键记录没有命中,因此解锁
yejr 2024-7-7 17:40:31
fancyghost 发表于 2024-7-7 17:16
create table t2 (
id int primary key,
c1 int,

是的,这就是InnoDB行锁的特点,其中有一条适合你这种场景

- 任何辅助索引上锁,或非索引列上锁,都要回溯到主键上再加锁

- 和其他session有冲突时,隐式锁转换为显式锁

也就是 S2 在扫描 c1 = 2 这个条件时(因为 c2 没有索引,扫描时会被忽略),匹配到 id = 3 这条记录,因此触发锁等待。
reddey 2024-7-7 20:36:16
yejr 发表于 2024-7-7 17:40
是的,这就是InnoDB行锁的特点,其中有一条适合你这种场景

- 任何辅助索引上锁,或非索引列上锁,都要回 ...

你的总结很到位
一个学艺不精的国产数据库爱好者
fancyghost

2

主题

0

博客

6

贡献

新手上路

Rank: 1

积分
10

合作电话:010-64087828

社区邮箱:greatsql@greatdb.com

社区公众号
社区小助手
QQ群
GMT+8, 2024-7-16 20:44 , Processed in 0.019139 second(s), 15 queries , Redis On.
快速回复 返回顶部 返回列表