行锁在 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
网友评论