你知道MySQL Innodb的锁,到底锁的是什么吗?
首先介绍下
Record Lock:记录锁/行锁,记录锁锁定的是索引记录。即使表没有定义索引,InnoDB也会创建一个隐藏的聚集索引,并使用这个索引来锁定记录。(RR和RC都起作用)
Gap Lock:间隙锁,他指的是在索引记录之间的间隙上的锁,或者在第一个索引记录之前或最后一个索引记录之后的间隙上的锁。(间隙锁只有在Repeatable Reads(RR)这种隔离级别中才会起作用。)
Next-Key:索引记录上的记录锁和索引记录之前间隙上的间隙锁的组合。
RR(可重复读)
Rc(读已提交)
测试(行锁)
开启事务a,修改id为60的行数据(id为唯一索引),事务a未提交,开启事务b修改id为58的数据,可以正常修改,此时锁的是id为60的这一行数据
普通索引
开启事务a,修改dept_no为60的数据(dept_no上普通索引,UPDATE dept set sex = 1 WHERE dept_no = 60 锁定的是该索引的结果,锁定id为59,60,77的数据),事务a未提交,开启事务b修改id in(59,60,77)的数据,不可以正常修改(也不能插入和删除),可以操作其他行
注意:当事务a语句为UPDATE dept set sex = 1 WHERE dept_no >60时会锁定dept_no大于60 的行(还是索引的结果),锁定dept_no > 60(新增、修改、删除)
测试(表锁)
开启事务a,修改dept_no为60的数据(dept_no上没有索引),事务a未提交,开启事务b修改id为58的数据,不可以正常修改,此时锁的是整个表(其他事务不能修改新增和删除)
死锁:一个事务锁住了表A,然后又访问表B;另一个事务锁住了表B,然后企图访问表A;这时就会互相等待对方释放锁,就导致了死锁。(RR) 隔离级别
很多大厂,为了提升并发度和降低死锁发生的概率,会把数据库的隔离级别从默认的 RR 调整成 RC。
总结:没有索引会锁表,有索引会锁定该索引的数据(行锁)
select * from dept WHERE dept_no =60 结果为59,60,77(图三)
Record Lock:锁定索引的记录id为(59,60,77)
Gap Lock: 锁定的是(-∞, 59)、(59,60)、(60,77)、(77,+∞)
Next-Key:索引的结果(-∞, 59]、(59,60]、(60,77]、(77,+∞],即Record Lock+Gap Lock
InnoDB的RR级别中,加锁的基本单位是 next-key lock,只要扫描到的数据都会加锁。
优化:
常用的修改条件上加索引,没有索引的修改是锁表
索引上的等值查询,给唯一索引加锁的时候,next-key lock 退化为行锁。