0%

当前读与快照读

本文是根据慕课相关课程学习后,并总结了以下几篇博文后做的总结
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

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