MySQL数据库行级锁之行锁

行级锁

行级锁,每次操作锁住对应的行数据。锁定粒度最小,发生锁冲突的概率最低,并发度最高。应用在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操作

执行插入的事务操作
MySQL数据库行级锁之行锁_第1张图片
查看此时行锁和意向锁的情况
在这里插入图片描述

update操作

执行更新的事务操作(id=88在表中不存在)
MySQL数据库行级锁之行锁_第2张图片
查看此时行锁和意向锁的情况
MySQL数据库行级锁之行锁_第3张图片
执行更新的事务操作(id=670在表中存在)
在这里插入图片描述
查看此时行锁和意向锁的情况
MySQL数据库行级锁之行锁_第4张图片

delete操作

执行删除的事务操作(id=99在表中不存在)
在这里插入图片描述
MySQL数据库行级锁之行锁_第5张图片
执行删除的事务操作(id=667在表中存在)
在这里插入图片描述
MySQL数据库行级锁之行锁_第6张图片

无索引行锁升级为表锁

score无索引

事务1:
MySQL数据库行级锁之行锁_第7张图片
单独只执行事务1时,查看此时行锁和意向锁的情况,会给每行都加行锁相当于加了表锁
MySQL数据库行级锁之行锁_第8张图片
事务2:
执行事务1后,再执行事务2,此时事务2会阻塞
在这里插入图片描述
查看此时行锁和意向锁的情况
MySQL数据库行级锁之行锁_第9张图片

score有索引

给score创建索引
MySQL数据库行级锁之行锁_第10张图片
查看此时行锁和意向锁的情况,此时插入不进去score在79之前的数据行均已上锁
MySQL数据库行级锁之行锁_第11张图片
在其他会话执行更新操作不会阻塞
在这里插入图片描述

你可能感兴趣的:(mysql,mysql)