1. InnoDB的行锁
行锁(row lock)也称为记录锁。顾名思义,就是锁住某一行(某个记录row)。需要注意的是,MySQL服务层并没有行锁机制,行级锁只在存储引擎层实现。
优点:锁定力度小,发生锁冲突概率低,可以实现的并发度高。
缺点:对于锁的开销比较大,加锁会比较慢,容易出现死锁的情况。
InnoDB与MyISAM的最大不同有两点:一是支持事务;二是采用了行级锁。
a. 记录锁(recode locks)
记录锁也就是仅仅把一条记录锁上,官方的类型名称为: LOCK_REC_NOT_GAP。比如我们把id值为8的那条记录加一个记录锁的示意图如图所示。仅仅是锁住了id值为s的记录,对周围的数据没有影响。
例子:行锁的S锁
select * from student where id = 1 lock in share mode;
b. 间隙锁(gap locks)
MySQL在REPEATABLE READ隔离级别下是可以解决幻读问题的,解决方案有两种,可以使用MVCC方案解决,也可以采用加锁方案解决。但是在使用加锁方案解决时有个大问题,就是事务在第一次执行读取操作时,那些幻影记录尚不存在,我们无法给这些幻影记录加上记录锁。InnoDB提出了一种称之为Gap Locks的锁,官方的类型名称为:LOCK_GAP,我们可以简称为gap锁。比如,把id值为8的那条记录加一个gap锁的示意图如下:
图中id值为8的记录加了gap锁,意味着不允许别的事务在id值为8的记录前边的间隙插入新记录,其实就是id列的值(3, 8)这个区间的新记录是不允许立即插入的。比如,有另外一个事务再想插入一条id值为4的新记录,它定位到该条新记录的下一条记录的id值为8,而这条记录上又有一个gap锁,所以就会阻塞插入操作,直到拥有这个gap锁的事务提交了之后,id列的值在区间(3,8)中的新记录才可以被插入。
gap锁的提出仅仅是为了防止插入幻影记录而提出的。虽然有共享gap锁和独占gap锁这样的说法,但是它们起到的作用是相同的。而且如果对一条记录加了gap锁(不论是共享gap锁还是独占gap锁),并不会限制其他事务这条记录加记录锁或者继续加gap锁。
例子:
这里session 2并不会被堵住。因为表里并没有id=5这个记录,因此session 1加的是间隙锁(3,8)。也是在这个间隙加的间隙锁。它们有共同的目标,即:保护这个间隙,不允许插入值。但,它们之间是不冲突的。
注意,给一条记录加了gap锁只是不允许其他事务往这条记录前边的间隙插入新记录,那对于最后的间隙,也就是student 表中id值为20的记录之后的间隙该咋办呢?也就是说给哪条记录加gap锁才能阻止其他事务插入id值在(20,+正无穷)这个区间的新记录呢?这时候我们在讲数据页时介绍的两条伪记录派上用场了。
- Infimum记录,表示该页面中最小的记录。
- Suprenum记录,表示改页面中最大的记录。
为了实现阻止其他事务插入id值在(20, +oo)这个区间的新记录,我们可以给索引中的最后一条记录,也就是id值为20的那条记录所在页面的Supremum记录加上一个gap锁。
标签:进阶,记录,间隙,行锁,值为,gap,插入,MySQL,id From: https://blog.csdn.net/2301_80912559/article/details/140719197