Bootstrap

【数据库】多版本并发控制(MVCC)理解

0 前言

需要的前置知识:

  • 事务
  • 读写并发一致性
  • 隔离级别

1 基本概念

1.1 MVCC介绍

  • MVCC是一种用来解决读写冲突的无锁并发控制。
  • MVCC和锁机制是MySQL数据库的InnoDB引擎实现事务隔离级别的手段。
  • MVCC主要是针对REPEATABLE READ和READ COMMITTED两个隔离级别。

1.2 MVCC的作用

  • 与锁不同,MVCC的快照读并不加速(乐观锁的一种实现),因此开销更低。
  • 在并发读写数据库时,可以做到读操作时不用阻塞写操作,写操作也不用阻塞读操作,提高了数据库并发读写的性能。

2 版本号和undo log

2.1 版本号

  • 系统版本号(SYS_ID):每开始一个新的事务,系统版本号自动递增。
  • 事务版本号(TRX_ID):事务开始时的系统版本号

2.2 undo log

2.2.1 隐藏字段

在数据库创建的时候,InnoDB会为每一行增加三个隐藏字段:

  • 隐藏主键(DB_ROW_ID):如果数据表没有主键,InnoDB会自动以DB_ROW_ID产生一个聚簇索引。
  • 最近修改/插入事务ID(DB_TRX_ID):记录创建这条记录/最后一次修改该记录的事务ID
  • 回滚指针(DB_ROLL_PTR):指向这条记录的上一个版本
    一条记录

2.2.2 undo log版本链

当一行数据被多个事务进行修改,每个事务修改后,MySQL都会保留修改前的数据(版本快照)到undo log中,并且由DB_ROLL_PTR把多个版本快照串联起来形成一个历史记录版本链。
在这里插入图片描述

3 快照读和读视图

3.1 快照读和当前读

  • 快照读:就是事务读取每条记录的版本快照,而不是当前最新的数据,所以不用加锁。
  • 当前读:读取的是最新版本,所以在读取之前需要获得对应记录的锁。

3.2 读视图(readview)

事务在进行快照读的时候会产生读视图,用来判断当前事务可以访问该记录的哪个版本快照。

3.2.1 readview的属性

  • m_ids:表示在生成“readview”时,当前系统中没提交事务的“事务id”列表。
  • min_trx_id:表示在生成“readview”时,当前系统中没提交读写事务中的最小“事务id”。
  • max_trx_id:表示在生成"readview"时,系统中应该分配给下一个事务的“事务id”
  • creator_trx_id:表示生成该“readview”的事务的事务"事务id"
    在这里插入图片描述

3.2.2 readview判断版本链中可用版本流程

1 如果被访问版本的trx_id与readview中的creator_trx_id值相同,表明当前事务在访问自己修改过的记录,该版本可以被当前事务访问;
2 如果被访问版本的trx_id小于readview中的min_trx_id值,表明生成该版本的事务在当前事务生成readview前已经提交,该版本可以被当前事务访问;
3 如果被访问版本的trx_id大于readview中的max_trx_id值,表明生成该版本的事务在当前事务生成readview后才开启,该版本不可以被当前事务访问;
4 如果被访问版本的trx_id在readview的min_trx_id和max_trx_id之间,需要在m_ids中去查找是否存在?

  • 如果存在,表示创建readview生成该版本的事务还未提交,该版本不可访问。
  • 如果不存在,表明创建readview生成该版本的事务已提交,该版本可以访问。

5 如果当前版本不可访问,则由roll_pointer回滚到上一个版本,重复1-4步骤,直到可以访问为止。

3.3 读取已提交(RC)和可重复读(RR)隔离级别下的快照读

  • 读取已提交:每次快照读都会生成一个readview,所以每次读都可以看到别的事务提交的数据。
  • 可重复读:第一次快照读会创建一个readview,之后每次使用快照读都使用同一个readview,可以避免不可重复读问题。
;