此次的内容是学习极客时间的MySQL实战45讲课程中的实验和总结,具体课程是第21篇文章。sql
首先是课程中的总结的加锁规则,两个“原则”、两个“优化”和一个“bug”(可重复读的事务隔离级别下)。学习
原则 1:加锁的基本单位是 next-key lock。但愿你还记得,next-key lock 是前开后闭区间。 原则 2:查找过程当中访问到的对象才会加锁。 优化 1:索引上的等值查询,给惟一索引加锁的时候,next-key lock 退化为行锁。 优化 2:索引上的等值查询,向右遍历时且最后一个值不知足等值条件的时候,next-key lock 退化为间隙锁。 一个 bug:惟一索引上的范围查询会访问到不知足条件的第一个值为止。
而后是此次用到的表和数据优化
CREATE TABLE `t` ( `id` int(11) NOT NULL, `c` int(11) DEFAULT NULL, `d` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `c` (`c`) ) ENGINE=InnoDB; insert into t values(0,0,0),(5,5,5), (10,10,10),(15,15,15),(20,20,20),(25,25,25);
再而后就是实际例子了3d
根据原则1加的next-key lock锁是id(5,10],由于id等于7的数据并不存在,因此不知足优化1,根据优化2将会退化为间隙锁id(5,10),从上面的实际例子中也能看出来,只有插入id=6的数据在等待锁,id=四、十一、十、5的数据在插入和更新的时候都正常。对象
这个和上一个例子相似区别是知足优化1因此就从next-key lock锁id(5,10],退化为id=5的行锁,因此id=6,4的数据能够插入进去,只有id=5的数据在更新的时候等待锁。blog
这种状况就是索引
因此id=四、11的数据能够插入,而id=六、10的数据的更新和插入的时候须要等待锁事务
分析:it
可是实际状况上id=11的数据插入也须要等待锁,这就是上面规则说的bug惟一索引上的范围查询会访问到不知足条件的第一个值为止,这里的id<=10,会一直扫描到id=15,因此会加上(10,15]的next-key lock锁class
这实际上是两个例子,由于只有一个区别就放一块儿了,先按照规则来分析
这两个加锁的区别就是对于id=5的锁的问题,lock in share mode没有对id=5加锁,因此能够获得的信息是,lock in share mode只锁覆盖索引,可是若是是 for update 就不同了。 执行 for update 时,系统会认为你接下来要更新数据,所以会顺便给主键索引上知足条件的行加上行锁。
这个和3例子相似,区别是这里不是主键,也就是说不是惟一索引,因此这里的分析过程就是
这个例子和第5个例子相似,区别就是limit的问题,由于规则中总结的bug能够解释,limit 1只须要扫描一行,因此c(5,10)的间隙锁就没加上,而limit 2就再次证实了,若是须要返回两条数据须要再扫描就加上了c(5,10)的间隙锁
没有order by的状况先来分析:
而后是有order by desc的状况:
这上面总结的规则,其实没啥道理可言,MySQL代码就是这样写的,加锁的意义是实际上为了保持数据的一致性和语义的正确,从例子4咱们就能看到明明咱们想锁的是5-10,可是由于bug(10,15]也加上了锁。因此考虑MySQL的这个加锁问题的时候,最好仍是根据扫描的状况来考虑
而后是一些细节的记录: