(25)行锁实现

2020-12-26  本文已影响0人  hedgehog1112

行锁在 InnoDB 中基于索引实现,如加锁没用索引,退化为表锁

概要:2 相同索引,访问不同行,锁冲突   

           3 多索引,不同索引锁定不同行

           4 小表或数据转换,可能表锁,不走索引

三种行锁:Record Lock(唯一索引/主键列 精确查找,否则退化)

                  Gap Lock(非唯一索引,不包含记录本身)

                  Next-Key Lock(非唯一索引,锁左开右闭,包含记录本身)

1、不通过索引查询时,InnoDB用表锁,不是行锁

没索引,加排他锁,等待    

加索引后

2、相同索引,访问不同行,锁冲突。行锁针对索引加锁,不对记录加锁

id有索引,name没索引

3、多索引时,不同事务可用 不同索引锁定不同行

主键、唯一或普通索引都用行锁:id主键索引,name普通索引

4、是否用索引通过执行计划决定,如全表扫描效率更高(小表),就不用索引,表锁,而不是行锁

检索值的数据类型索引字段不同,虽MySQL能转换,但不用索引,导致表锁

name是varchar,不和varchar比较,转换name

二、三种行锁

1、记录锁(Record Locks)

    1)id 列必须为唯一索引主键列    2) 必须为精准匹配(=),不能为 >、<、like等

否则退化临键锁

2、间隙锁(Gap Locks)

基于非唯一索引锁间,不包含记录本身。基于Next-Key Locking 算法

    SELECT * FROM table WHERE id BETWEN 1 AND 10 FOR UPDATE;

    锁住(1,10), 2、3、4、5、6、7、8、9阻塞,1 和 10 不被锁

ps:除手动加锁,执行完某些 SQL ,InnoDB 自动加间隙锁

3、临键锁(Next-Key Locks)

特殊间隙锁包含记录本身解决幻读

1)每个非唯一索引列都有临键锁(只与非唯一索引列有关),锁左开右闭

2)UPDATE、FOR UPDATE、LOCK IN SHARE MODE操作时,InnoDB 获取记录行临键锁

3)例:age 临键锁:(-∞, 10],(10, 20],(20, 30],(30, +∞]    锁住 (10, 30)

事务 A: UPDATE table SET name = Vladimir WHERE age = 20  或    SELECT * FROM table WHERE age = 20 FOR UPDATE;        获取(20, 30] 临键锁

事务 B :INSERT INTO table VALUES(100, 20, 'Aragorn');    或  INSERT INTO table VALUES(100, 26, 'Aragorn');   被阻塞

INSERT INTO table VALUES(100, 20, 'Aragorn');

https://zhuanlan.zhihu.com/p/147543803

https://blog.csdn.net/haitun312366/article/details/8257844

上一篇 下一篇

猜你喜欢

热点阅读