行级锁
行级锁,每次操作锁住对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在InnoDB存储引擎中。
InnoDB的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。对于行级锁,主要分为以下三类:
-
行锁(Record Lock)
锁定单个行记录的锁,防止其他事务对此行进行update和delete。在
RC、RR隔离级别下都支持。 -
间隙锁(Gap Lock)
锁定索引记录间隙(不含该记录),确保索引记录间隙不变,防止其他事务在这个间隙进行insert,产生幻读。在RR隔离级别下都支持。 -
临键锁(Next-Key Lock)
行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙Gap。在RR隔离级别下支持。
行锁
InnoDB实现了以下两种类型的行锁:
- 共享锁(S):允许一个事务去读一行,阻止其他事务获得相同数据集的排它锁。
- 排他锁(X):允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁。
S(共享锁) | X(排他锁) | |
---|---|---|
S(共享锁) | 兼容 | 冲突 |
X(排他锁) | 冲突 | 冲突 |
常见的SQL语句,在执行时所加的行锁如下:
SQL 语句 | 行锁类型 | 说明 |
---|---|---|
INSERT | 排他锁 | 自动加锁 |
UPDATE | 排他锁 | 自动加锁 |
DELETE | 排他锁 | 自动加锁 |
SELECT(正常) | 不加任何锁 | |
SELECT … LOCK IN SHARE MODE | 不加任何锁 | 需要手动在SELECT之后加LOCK IN SHARE MODE |
SELECT … FOR UPDATE | 排他锁 | 需要手动在SELECT之后加FOR UPDATE |
演示
默认情况下,InnoDB在 REPEATABLE READ事务隔离级别运行,InnoDB使用 next-key 锁进行搜索和索引扫描,以防止幻读。
- 针对唯一索引进行检索时,对已存在的记录进行等值匹配时,将会自动优化为行锁。
- InnoDB的行锁是针对于索引加的锁,不通过索引条件检索数据,那么InnoDB将对表中的所有记录加锁,此时就会升级为表锁。
insert操作
执行插入的事务操作
查看此时行锁和意向锁的情况
update操作
执行更新的事务操作(id=88在表中不存在)
查看此时行锁和意向锁的情况
执行更新的事务操作(id=670在表中存在)
查看此时行锁和意向锁的情况
delete操作
执行删除的事务操作(id=99在表中不存在)
执行删除的事务操作(id=667在表中存在)
无索引行锁升级为表锁
score无索引
事务1:
单独只执行事务1时,查看此时行锁和意向锁的情况,会给每行都加行锁相当于加了表锁
事务2:
执行事务1后,再执行事务2,此时事务2会阻塞
查看此时行锁和意向锁的情况
score有索引
给score创建索引
查看此时行锁和意向锁的情况,此时插入不进去score在79之前的数据行均已上锁
在其他会话执行更新操作不会阻塞