nextkey锁的引入是为了防止幻读的问题,也就是防止在读扫描的过程中有人插入,导致第二次扫描出来的结果不一致。
举例如下:
表数据如下:
1,5,6,7,8
事务1 事务2
扫描1
扫描5
插入2(此时如果没有nextkey锁,插入将是成功的)
事务2提交
扫描6,7,8
不关事务重新开始扫描
此时将扫描到事务2插入的行。造成幻读
所谓幻读就是同一个事务的两次扫描结果不一致。
而为了解决幻读问题,引入nextkey锁。如何保证呢:操作如下
事务1 事务2
扫描1(加锁)
扫描5(加锁)
插入2(需要对插入的下一行加锁,因为定位到5的位置,因此需要对5加锁,此时因为事务1已经对5加锁,导致事务2等待)
扫描6(加锁)
扫描7(加锁)
扫描8(加锁)
不关事务重新扫描
因为都加锁了,所以扫描是没有问题的。
事务提交(放掉行锁)
插入获得锁,开始插入。
事务2提交
上述步骤可以看出,通过nextkey锁,事务二的插入会因为事务1的扫描加锁而等待。
扫描的过程中如果需要加nextkey锁,则需要将所有的扫描行加锁,并将边界加锁。
如下例子:
1,2,3,4,7,9,10
扫描条件是 >=1 and <=4
那么扫描加锁应该是 1,2,3,4
扫描条件是 >=1
那么扫描加锁应该是 1,2,3,4,7,9,10,maxkey这里的maxkey是个虚拟的值,防止插入事务插入时插入到10之后
扫描条件是 <=1
那么扫描加锁应该是 1对于小于1的插入一定要加上1的锁之后插入
扫描条件是>1则不需要对1加锁,同时扫描到末尾时还需要对maxkey加锁