fancyghost 发表于 2024-7-6 20:47:15

RC隔离级别下的加锁问题咨询

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上加锁?


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行锁的特点,其中有一条适合你这种场景

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

你的总结很到位
页: [1]
查看完整版本: RC隔离级别下的加锁问题咨询