MYSQL-- 行锁在索引命中与覆盖情况下的加锁行为
一、行锁与索引
行锁(Record Lock):锁住索引记录对应的行。
索引相关概念
术语 解释 索引命中 查询条件用到了某个索引 索引覆盖 查询的字段完全包含在索引中,不需要访问数据行(回表) 索引未命中 查询条件没有用到任何索引,进行全表扫描
二、详细分析
1. 行锁(Record Lock)
a. 索引命中 + 索引覆盖
行为:只锁住索引记录对应的行。
性能:最优,锁粒度细,避免不必要的锁冲突。
示例
CREATE TABLE users (id INT PRIMARY KEY,name VARCHAR(50),age INT,INDEX idx_age(age) );-- 查询使用 age 索引,并且只查询 age 字段(覆盖索引) SELECT age FROM users WHERE age = 30 FOR UPDATE;
加锁范围:锁住 age=30 对应的索引记录。
不回表,锁更轻。
b. 索引命中,但非覆盖索引(需要回表)
行为:锁住索引记录对应的行,然后回表锁住对应的聚簇索引记录(InnoDB 主键索引的记录)。
性能:略低于覆盖索引,因为要回表。
示例
-- 查询用索引条件,但查询列不全在索引中 SELECT name FROM users WHERE age = 30 FOR UPDATE;
首先锁住 age=30 的索引记录
回表访问聚簇索引记录,对主键索引记录加行锁
锁范围更大,开销稍大
c. 索引未命中(全表扫描)
行为:无法定位具体行,InnoDB 会锁整张表(表锁)。
性能:最差,锁冲突多。
示例
SELECT * FROM users WHERE name = 'Alice' FOR UPDATE;
如果
name
没有索引,则全表扫描无法加行锁,退化为表锁
影响其他并发事务