本文是根据慕课相关课程学习后,并总结了以下几篇博文后做的总结
https://blog.csdn.net/silyvin/article/details/79280934
https://www.cnblogs.com/cat-and-water/p/6427612.html
innodb的默认事务隔离级别是rr(可重复读)。它的实现技术是mvcc。基于版本的控制协议。该技术不仅可以保证innodb的可重复读,而且可以防止幻读。但是它防止的是快照读,也就是读取的数据虽然是一致的,但是数据是历史数据。如何做到保证数据是一致的(也就是一个事务,其内部读取对应某一个数据的时候,数据都是一样的),同时读取的数据是最新的数据。innodb提供了一个间隙锁的技术。也就是结合GAP锁与行锁,达到最终目的。当使用索引进行插入的时候,innodb会将当前的节点和上一个节点加锁。这样当进行select的时候,就不允许加x锁。那么在进行该事务的时候,读取的就是最新的数据。
快照读(snapshot read)
- 不加锁的非阻塞读
- 当前读(current read)
- select … lock in share mode - select … lock in share mode
- select … for update
- insert
- update
- delete
- select … lock in share mode - select … lock in share mode
RC、RR级别下的InnoDB的非阻塞读如何实现
- 数据行里的DB_TRX_ ID(事务ID)、DB_ ROLL_PTR(回滚指针)、DB_ROW_ ID(行号)字段
- undo日志
- 进行变更操作会产生undo日志,存储老版本数据
- 分为insert undo log(存储insert日志,只在事务回滚时需要,事务提交后即可删除)和update undo log(存储delete和update日志,不仅回滚需要,快照读也需要,不可随便删除)
下面我们看一下演示
上图为将field2字段由12改为32。此时我们将原数据存出来undo log,我们将回滚指针指向undo log的原数据,同时DB_TRX_ ID加1。如果我们之后进行回滚,则从undo log中获取数据,进行回滚。
同样下图为两个undo log日志
InnoDB可重复读隔离级别下如何避免幻读
- 表象:快照读(非阻塞读) –伪MVCC
- 内在: next-key锁(行锁+GAP锁)
对主键索引或者唯一索引会用Gap锁吗??
- 如果where条件全部命中,则不会用Gap锁,只会加记录锁
- 如果where条件部分命中或者全不命中,则会加Gap锁
如数据库中存在id为1,3,5的值,如果我们查询where id in (1,3); 此时我们会发现只有行锁,我们update id= 2;是成功的,但是如果我们查询where id in (1,4); 此时我们会发现有Gap锁,我们update id= 2;是无法成功的,只有等查询事务结束后才能update