MVCC详细讲解

  今天小编给大家分享的是MVCC的详细介绍,相信很多人都不太了解,为了让大家更加了解MVCC,所以给大家总结了以下内容,话不多说,一起往下看吧。
  1. MVCC的实现,是通过保存数据在某个时间点的快照来实现的,也就是说,不管需要执行多长时间,每个事务看到的数据是一致的,根据事务开始的时间不同,每个事务对同一张表,同一时刻看到的数据可能是不一样的。
  2. innodb在基于锁的并发控制技术上,实现了MVCC技术,innodb的MVCC技术有以下几个特点:
    • 事务的标识,依靠事务ID,是一个全局唯一的64bits数值
    • 多版本,是元组级的多版本,而不是oracle实现的是页面级的多版本
    • 最新的数据存储在数据页面中,其他数据的旧版本存储在回滚段中
  3. 因为innodb的多版本是元组级的版本,所以在每个记录上,有一些与并发和回滚等于事务相关的隐含字段
    • DATA_TRX_ID: 6字节长,表示上一个执行插入或更新操作的事务
    • DATA_ROLL_PTR: 7字节长,表示旧版本的数据位于回滚段中的位置,指向的是一个旧版本,只有元组被更新,才有会新版本产生,旧版本被置于回滚段,因此一致性无锁读操作按照“read view”快照需要读取旧版本时,只能根据事务ID回到回滚段中寻找旧版本
    • DATA_ROW_ID:6字节长,表示执行插入操作后生成的单调自增长的行的ID标识,如果存在聚集索引,索引项则包括的是这个DB_ROW_ID值
    • DELETE_BIT: 删除标志位
  4. 位于回滚段中的UNDO日志分为两种
    • INSERT UNOD LOGS:插入到回滚段的日志,仅用于事务提交时使用,当事务提交,则对应的INSETR UNDO LOGS里面的内容被清除
    • UPDATE UNDO LOGS:被用于一致性无锁读,为一致性读提供快照隔离下的可被读取的老版本数据,当没有需要满足一致性读的快照时,一些老版本数据才被清理
  5. MVCC的工作机制
    • innodb的MVCC,是通过在每行记录后面保存两个隐藏的列来实现的,这两个列,一个保存的行的创建时间,一个保存行的过期时间,当然存储的并不是实际的时间值,而是系统版本号(system version number),每开始一个新的事务,系统版本号就会递增,事务开始时刻的系统本号会作为事务的版本号,用来和查询到的每行记录的版本号进行记录,下面看一个在REPEATABLE READ隔离级别下,MVCC是如何操作的
    • SELECT
      • innodb会根据以下两个条件检查每行记录,只有符合下面两个条件的记录,才能返回作为查询结果
        1. innodb值只查找系统早已当前事务版本的数据行(也就是行的系统版本号小于或等于事务的系统版本号),这样可以确保事务读取的行,要么是在事务开始前就已经存在的,要不是事务自身插入或者修改过的
        2. 行的删除版本要不未定义,要不大于当前事务版本号,这可以确保事务读取到的行,在事务开始之前未被删除
    • INSERT
      • innodb为新插入的每一行保存当前系统版本号作为行版本号
    • DELETE
      • innodb为删除的每一行保存当前系统版本号作为行删除标识
    • UPDATE
      • innodb为插入一条新纪录,保存当前系统版本号作为行版本号,同时保存当前系统的版本号到原先的行作为删除标识
  6. 保留着两个额外系统版本号,使得大多数读操作读不需要加锁。这样设计使得读数据操作很简单,性能很好,并且也能保证只会读取到符合标准的行,不足之处是每行记录都需要额外的存储空间,需要做更多的行检查工作,以及一些额外的维护工作
  7. MVCC只在REPEATABLE READ和READ COMMIT两个隔离级别下工作,其他两个隔离级别都和MVCC不兼容,因为READ UNCOMMIT总是读取最新的数据行,而不是符合当前事务版本的数据行,而SERIALIZEABLE则会对所有读取的行都加锁
  8. 下面我们就开始案例:
    *MVCC详细讲解
    • 我们执行step7的时候发现一个问题,怎么id=4的查不出来呢,按照上面的规则,id=3的事务ID是2,T3的事务ID是3,这种情况id=4是可以查出来的呢,所以说上面的规则肯定还说的不是很详细,有遗落的地方,我们接着往下面看
  9. 我们在事务隔离中可以知道,innodb在执行select的时候会创建一个快照
    • 隔离级别大于等于可重复读:事务块的所有的SELECT操作都要使用同一个快照,此快照是在第一个SELECT操作时建立的

      MVCC详细讲解