行级锁,每次操作锁住对应的行数据,锁定粒度最小,发生锁冲突的概率最低,并发度最高。英英在innodb存储引擎中。
innodb的数据是基于索引组织的,行锁是通过对索引上的索引项加锁来实现的,而不是对记录加的锁。对于行级锁,主要分为以下三类:
1、行锁(record lock):锁定单个行记录的锁,防止其他事务对此行进行update和delete。在RC、RR隔离级别下都支持。
2、间隙锁(GAP lock):锁定索引记录间隙(不含该记录),确保所有记录间隙不变,防止其他事务在这个间隙进行insert,产生幻读,在RR隔离级别下都支持。
3、临键锁(next-key lock):行锁和间隙锁组合,同时锁住数据,并锁住数据前面的间隙gap,在RR隔离级别下支持。
一、行锁。
innodb实现以下两种类型的行锁。
1、共享锁(S):允许一个事务去读一行,阻止其他事务获得相同的数据集的排他锁。
2、排他锁(X):允许获取排他锁的事务更新数据,阻止其他事务获得相同数据集的共享锁和排他锁。
当前所类型/请求锁类型 | S(共享锁) | X(排他锁) |
S(共享锁) | 兼容 | 冲突 |
X(排他锁) | 冲突 | 冲突 |
3、操作增删改查时加的行锁类型。
SQL | 行锁类型 | 说明 |
insert | 排他锁 | 自动加锁 |
update | 排他锁 | 自动加锁 |
delete | 排他锁 | 自动加锁 |
select(正常) | 不加任何锁 | |
select ... lock in share mode | 共享锁 | 需要手动在select之后加 lock in share mode |
select ... for update | 排他锁 | 需要手动在select之后加 for update |
4、演示。
默认情况下,innodb在repeatable事务隔离级别运行,innodb使用next-key锁进行搜索和索引扫描,以防止幻读。
a.针对唯一索引进行检索时,对已存在的记录进行等值匹配时,将会自动优化为行锁。
共享锁之间兼容
释放第二个事务的行锁
共享锁和排他锁不兼容,id为3的可以修改,id为1的不能修改,因为id为1加了行锁。
排他锁互斥,提交后即可修改。
b. innodb的行锁是针对于索引加的锁,不通过索引条件检索数据,那么innodb将对表中的所有记录加锁,此时就会升级为表锁。
name没有索引,所以对所有的记录加锁,升级为表锁,所以阻塞了。
给name加索引,成功执行。
二、间隙锁和临键锁。
默认情况下,innodb在repeatable read事务隔离级别运行,innodb使用next-key锁进行搜索和索引扫描,以防止幻读。
1、索引上的等值查询(唯一索引),给不存在的记录加锁时,优化为间隙锁。
间隙锁锁住,不能插入新数据
事务提交后,成功添加新数据
2、索引上的等值查询(普通索引),向右遍历时最后一个值不满足查询需求时,next-key lock退化为间隙锁。
非唯一等值索引,为了避免出现幻读现象,加上一把间隙锁。
3、索引上的范围查询(唯一索引)会访问到不满足条件的第一个值为止。
范围查询时给19加行锁锁住,加临键锁直接25这一行及25之前的间隙,加临键锁锁正无穷大以及正无穷到25之间的间隙。
注意:间隙锁唯一目的是防止其他事务插入间隙,间隙锁可以共存,一个事务采用的间隙锁不会组织另一个事务在同一间隙上采用间隙锁。
间隙锁锁的是间隙,不包含对应的数据记录,临键锁不仅会包含当前的数据记录,也会锁定该数据记录之前的间隙。