幻读:前后多次读取,数据总量不一致。
即使把所有的记录都加上锁,还是阻止不了新插入的记录,这是因为给行加锁的时候,这条记录还不存在,没法加锁。
解决方案:间隙锁 (Gap Lock)
间隙锁:在一行行扫描的过程中,不仅将给行加上了行锁,还给行两边的空隙,也加上了间隙锁。
行锁,分成读锁和写锁。跟行锁有冲突关系的是“另外一个行锁”。
但是间隙锁不一样,跟间隙锁存在冲突关系的,是“往这个间隙中插入一个记录”这个操作。间隙锁之间都不存在冲突关系。
间隙锁和行锁合称 next-key lock,每个 next-key lock 是前开后闭区间。
间隙锁和 next-key lock 的引入,帮我们解决了幻读的问题,但同时也带来了一些“困扰”。
行不存在的情况,无法加行锁,只能加间隙锁,然后间隙锁相互间不冲突,这样就及其容易死锁。
间隙锁的引入,可能会导致同样的语句锁住更大的范围,这其实是影响了并发度的。
间隙锁是在可重复读隔离级别下才会生效的。所以,你如果把隔离级别设置为读提交的话,就没有间隙锁了。 但同时,你要解决可能出现的数据和日志不一致问题,需要把
binlog 格式设置为 row。这,也是现在不少公司使用的配置组合。
可重复读的场景:金融的业务,财务需要统计过去一段时间内某些数据,需要反复根据某些条件查找,此时如果有新数据行插入,会导致统计时发生数据不一致的情况,此时需要使用可重复读的隔离级别。
由于重复读中有gap锁大大增加了锁等待和死锁概率 ,很大程度上要求你要保证不同事务内的相同逻辑sql的顺序性(这个不好理解 你需要多想下)
,提交读相比重复读 他的并发性得到了一个很好的保证(锁等待少)从所以在真实业务场景下,当我们修改一组数据时,
这组数据是否需要保证一致性,如果一致性要求没那么强,可以使用提交读 (事务内 多次查询数据 有可能不一致) ,这样你并发会提高很多 减少了锁冲突的概率。
然后,在备份期间,备份线程用的是可重复读,而业务线程用的是读提交。同时存在两种事务隔离级别,会不会有问题?
没有问题,不管是提交读还是可重复读,都是MVCC支持,唯一的不同,就是生成快照的时间点不同,也就是能够看到的数据版本不同,即使是提交读情况下,多个不同的事物时间不也是这种情况吗,所以相互并不影响。